Android 利用OSMdroid开发GIS

1、地址

Github地址:https://gitee.com/mirrors/osmdroid

Git地址:

GitCode - 全球开发者的开源社区,开源代码托管平台

Git下载包地址:Releases · osmdroid/osmdroid · GitHub

  1. 新建项目

osmdroid在线:

(1)添加依赖

(2)布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><org.osmdroid.views.MapViewandroid:id="@+id/mapView"android:layout_width="match_parent"android:layout_height="match_parent"/><Buttonandroid:id="@+id/btnLocation"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="定位"android:layout_margin="10dp"android:layout_alignParentTop="true"/></RelativeLayout>

(3)代码MainActivity.java

package com.chy.osmdroid;import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.chy.layers.LayerTileSources;
import com.chy.permission.PermissionUtils;
import org.osmdroid.api.IMapController;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.CustomZoomButtonsController;
import org.osmdroid.views.MapView;public class MainActivity extends AppCompatActivity {private static final int REQUEST_PERMISSION_CODE = 0;// 权限所用// 动态申请权限private String[] permissions = {Manifest.permission.INTERNET,// 网络权限Manifest.permission.ACCESS_COARSE_LOCATION,// 精细定位Manifest.permission.ACCESS_FINE_LOCATION,// 粗定位Manifest.permission.ACCESS_WIFI_STATE,// 定位权限Manifest.permission.ACCESS_NETWORK_STATE,Manifest.permission.WRITE_EXTERNAL_STORAGE};private MapView mapView;private LocationManager locationManager;// 定位管理器private Button btnLocation;// 定位按钮private boolean isLocation = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getPermission();// 获取权限initControls();}/*** 权限* */private void getPermission(){if (PermissionUtils.hasPermissions(MainActivity.this, permissions)) {initMap();// 调用初始化地图} else {PermissionUtils.requestPermissions(MainActivity.this, REQUEST_PERMISSION_CODE, permissions);Toast.makeText(getApplicationContext(), "地图加载失败!", Toast.LENGTH_SHORT).show();}}// 地图初始化private void initMap(){// 获取mapView实例mapView = findViewById(R.id.mapView);// 加载在线地图mapView.setTileSource(LayerTileSources.AutoNaviVector);// 设置最小缩放比例mapView.setMinZoomLevel(3.0);// 设置最大缩放比例mapView.setMaxZoomLevel(18.0);IMapController mapController = mapView.getController();// 设置地图初始级别mapController.setZoom(11.0);// 设置初始中心点GeoPoint centerPoint = new GeoPoint(43.90, 125.33);mapController.setCenter(centerPoint);//启用缩放及滑动手势//mapView.setBuiltInZoomControls(true);// 废弃得方法,被下面方法所替代mapView.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);mapView.setMultiTouchControls(true);}// 控件初始化private void initControls(){btnLocation = findViewById(R.id.btnLocation);// 点击事件btnLocation.setOnClickListener(new View.OnClickListener() {@SuppressLint("MissingPermission")@Overridepublic void onClick(View v) {//创建位置管理器实例locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);if (!isLocation){// 注册位置监听器locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);isLocation = !isLocation;}else {// 停止位置更新locationManager.removeUpdates(locationListener);isLocation = !isLocation;Toast.makeText(getApplicationContext(),"停止位置更新",Toast.LENGTH_SHORT).show();}}});}/*** 定位监听* */LocationListener locationListener = new LocationListener() {@Overridepublic void onLocationChanged(Location location) {// 处理位置变化double latitude = location.getLatitude();double longitude = location.getLongitude();Toast.makeText(getApplicationContext(),"lat:"+latitude+"lon:"+longitude,Toast.LENGTH_SHORT).show();// 在地图上显示当前位置// ...}@Overridepublic void onStatusChanged(String provider, int status, Bundle extras) {Toast.makeText(getApplicationContext(),"onStatusChanged",Toast.LENGTH_SHORT).show();}@Overridepublic void onProviderEnabled(String provider) {Toast.makeText(getApplicationContext(),"onProviderEnabled",Toast.LENGTH_SHORT).show();}@Overridepublic void onProviderDisabled(String provider) {Toast.makeText(getApplicationContext(),"onProviderDisabled",Toast.LENGTH_SHORT).show();}};@Overrideprotected void onDestroy() {super.onDestroy();// 停止位置更新if (locationManager != null){locationManager.removeUpdates(locationListener);}}
}

(4)代码LayerTileSources.java

package com.chy.layers;import android.util.Log;import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.tileprovider.tilesource.XYTileSource;
import org.osmdroid.util.MapTileIndex;/*** 谷歌、高德等瓦片地图** @author jiang zhu on 2019/10/18*/
public class LayerTileSources extends TileSourceFactory {//谷歌卫星混合public static final OnlineTileSourceBase GoogleHybrid = new XYTileSource("Google-Hybrid",0, 19, 512, ".png", new String[]{"http://mt0.google.cn","http://mt1.google.cn","http://mt2.google.cn","http://mt3.google.cn",}) {@Overridepublic String getTileURLString(long pMapTileIndex) {Log.d("url", getBaseUrl() + "/vt/lyrs=y&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex));return getBaseUrl() + "/vt/lyrs=y&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);}};//谷歌卫星public static final OnlineTileSourceBase GoogleSat = new XYTileSource("Google-Sat",0, 19, 512, ".png", new String[]{"http://mt0.google.cn","http://mt1.google.cn","http://mt2.google.cn","http://mt3.google.cn",}) {@Overridepublic String getTileURLString(long pMapTileIndex) {return getBaseUrl() + "/vt/lyrs=s&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);}};//谷歌地图public static final OnlineTileSourceBase GoogleRoads = new XYTileSource("Google-Roads",0, 18, 512, ".png", new String[]{"http://mt0.google.cn","http://mt1.google.cn","http://mt2.google.cn","http://mt3.google.cn",}) {@Overridepublic String getTileURLString(long pMapTileIndex) {return getBaseUrl() + "/vt/lyrs=m&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);}};//谷歌地形public static final OnlineTileSourceBase GoogleTerrain = new XYTileSource("Google-Terrain",0, 16, 512, ".png", new String[]{"http://mt0.google.cn","http://mt1.google.cn","http://mt2.google.cn","http://mt3.google.cn",}) {@Overridepublic String getTileURLString(long pMapTileIndex) {return getBaseUrl() + "/vt/lyrs=t&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);}};//谷歌地形带标注public static final OnlineTileSourceBase GoogleTerrainHybrid = new XYTileSource("Google-Terrain-Hybrid",0, 16, 512, ".png", new String[]{"http://mt0.google.cn","http://mt1.google.cn","http://mt2.google.cn","http://mt3.google.cn",}) {@Overridepublic String getTileURLString(long pMapTileIndex) {return getBaseUrl() + "/vt/lyrs=p&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);}};//高德地图public static final OnlineTileSourceBase AutoNaviVector = new XYTileSource("AutoNavi-Vector",0, 20, 256, ".png", new String[]{"https://wprd01.is.autonavi.com/appmaptile?","https://wprd02.is.autonavi.com/appmaptile?","https://wprd03.is.autonavi.com/appmaptile?","https://wprd04.is.autonavi.com/appmaptile?",}) {@Overridepublic String getTileURLString(long pMapTileIndex) {return getBaseUrl() + "x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z="+ MapTileIndex.getZoom(pMapTileIndex) + "&lang=zh_cn&size=1&scl=1&style=7&ltype=7";}};}

(5)权限代码

AndroidManifest.xml权限代码

<uses-permission android:name="android.permission.INTERNET" /><uses-permission  android:name="android.permission.ACCESS_COARSE_LOCATION"/><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

PermissionUtils.java 代码

package com.chy.permission;import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;import androidx.annotation.NonNull;
import androidx.annotation.Size;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import java.util.ArrayList;
import java.util.List;/*** 动态申请权限工具类* Created by xiaoyehai on 2018/4/25 0025.*/
public class PermissionUtils {public static final int GOTO_SEETING_CODE = 152;/*** 判断是否有权限** @param context* @param perms* @return*/public static boolean hasPermissions(@NonNull Context context, @Size(min = 1) @NonNull String... perms) {if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {return true;}if (context == null) {throw new IllegalArgumentException("Can't check permissions for null context");}for (String perm : perms) {if (ContextCompat.checkSelfPermission(context, perm) != PackageManager.PERMISSION_GRANTED) {return false;}}return true;}/*** 申请权限*/public static void requestPermissions(@NonNull Activity activity, int requestCode, String[] permissions) {List<String> permissionList = new ArrayList<>();for (String permission : permissions) {if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {permissionList.add(permission);}}String[] permissionsArray = permissionList.toArray(new String[permissionList.size()]);//将List转为数组if (permissionList.isEmpty()) {//不可能为空} else {ActivityCompat.requestPermissions(activity, permissionsArray, requestCode);//返回结果onRequestPermissionsResult}}/*** 申请权限的回调** @param requestCode  请求权限时传入的请求码,用于区别是哪一次请求的* @param permissions  所请求的所有权限的数组* @param grantResults 权限授予结果,和 permissions 数组参数中的权限一一对应,元素值为两种情况,如下:*                     授予: PackageManager.PERMISSION_GRANTED*                     拒绝: PackageManager.PERMISSION_DENIED*/public static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,@NonNull int[] grantResults, @NonNull PermissionCallbacks callBack) {//授予的权限。List<String> granted = new ArrayList<>();//拒绝的权限List<String> denied = new ArrayList<>();for (int i = 0; i < permissions.length; i++) {String perm = permissions[i];if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {granted.add(perm);} else {denied.add(perm);}}if (null != callBack) {if (denied.isEmpty()) {callBack.onPermissionsAllGranted(requestCode, granted, denied.isEmpty());}if (!denied.isEmpty()) {callBack.onPermissionsDenied(requestCode, denied);}}}/*** 用户是否拒绝权限,并检查“不要提醒”。** @param activity* @param perms* @return*/public static boolean somePermissionPermanentlyDenied(Activity activity, @NonNull List<String> perms) {for (String deniedPermission : perms) {if (permissionPermanentlyDenied(activity, deniedPermission)) {return true;}}return false;}public static boolean permissionPermanentlyDenied(Activity activity, @NonNull String perms) {if (!ActivityCompat.shouldShowRequestPermissionRationale(activity, perms)) {return true;}return false;}public static void showDialogGoToAppSettting(final Activity activity) {AlertDialog dialog = new AlertDialog.Builder(activity).setMessage("去设置界面开启权限").setPositiveButton("确定", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {// 跳转到应用设置界面goToAppSetting(activity);}}).setCancelable(false).show();}/*** 跳转到应用设置界面*/public static void goToAppSetting(Activity activity) {Intent intent = new Intent();intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);Uri uri = Uri.fromParts("package", activity.getPackageName(), null);intent.setData(uri);activity.startActivityForResult(intent, GOTO_SEETING_CODE);}public static void showPermissionReason(final int requestCode, final Activity activity, final String[] permission, String s) {AlertDialog dialog = new AlertDialog.Builder(activity).setMessage(s).setPositiveButton("确定", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {requestPermissions(activity, requestCode, permission);}}).setCancelable(false).show();}public interface PermissionCallbacks {/*** @param isAllGranted 是否全部同意*/void onPermissionsAllGranted(int requestCode, List<String> perms, boolean isAllGranted);/***/void onPermissionsDenied(int requestCode, List<String> perms);}
}

(6)加载离线地图

// 加载离线地图OSMDroid支持多种地图文件格式,如MBTiles、SQLiteDatabase、ZIP文件等String strFilepath = Environment.getExternalStorageDirectory().getPath() +"/osmdroid/xian.mbtiles";  // 在 此处替换自己的资源File exitFile = new File(strFilepath);String fileName = "xian.mbtiles";if (!exitFile.exists() && !fileName.contains(".")) {mapView.setTileSource(org.osmdroid.tileprovider.tilesource.TileSourceFactory.MAPNIK);} else {fileName = fileName.substring(fileName.lastIndexOf(".") + 1);if (fileName.length() == 0)return;/**** extensionMap.put("zip", ZipFileArchive.class);if(VERSION.SDK_INT >= 10) {extensionMap.put("sqlite", DatabaseFileArchive.class);extensionMap.put("mbtiles", MBTilesFileArchive.class);extensionMap.put("gemf", GEMFFileArchive.class);}这里加载上面四种地图格式*/if (ArchiveFileFactory.isFileExtensionRegistered(fileName)) {try {OfflineTileProvider tileProvider = new OfflineTileProvider(newSimpleRegisterReceiver(getApplicationContext()),new File[]{exitFile});mapView.setTileProvider(tileProvider);String source = "";IArchiveFile[] archives = tileProvider.getArchives();if (archives.length > 0) {Set<String> tileSources = archives[0].getTileSources();if (!tileSources.isEmpty()) {source = tileSources.iterator().next();mapView.setTileSource(FileBasedTileSource.getSource(source));} else {mapView.setTileSource(org.osmdroid.tileprovider.tilesource.TileSourceFactory.DEFAULT_TILE_SOURCE);}} elsemapView.setTileSource(org.osmdroid.tileprovider.tilesource.TileSourceFactory.DEFAULT_TILE_SOURCE);} catch (Exception ex) {ex.printStackTrace();}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/434596.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Hive和Hadoop的图书分析系统

本项目是一个基于大数据技术的图书分析系统&#xff0c;旨在为用户提供全面的图书信息和深入的图书销售及阅读行为分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以…

基于SSM+微信小程序的校园二手数码交易平台系统(二手3)(源码+sql脚本+视频导入教程+文档)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于ssm微信小程序的校园二手数码交易平台满足了不同用户的功能需求&#xff0c;包括用户、卖家以及管理员&#xff0c;下面对这不同用户的功能需求进行简介。 &#xff08;1&#xff09…

正点原子——DS100示波器操作手册

目录 基础按键&#xff1a; 快捷键 主界面&#xff1a; 垂直设置&#xff1a; 通道设置&#xff1a; 探头比列&#xff1a; 垂直档位&#xff1a; 垂直偏移&#xff1a; 幅度单位&#xff1a; 水平设置&#xff1a; 触发方式&#xff1a; 测量和运算: 光标测量&am…

队列及笔试题

队列 先进先出 使用单链表进行队尾插入 队头删除 其中带头结点直接尾插&#xff0c;不带头结点第一次操作要判断一下 但是带头结点需要malloc和free 函数传需要修改的参数方法 1、二级指针 2、带哨兵位的头结点 3、返回值 4、如果有多个值&#xff0c;用结构体封装起来…

深入解析Debian与Ubuntu:技术特点与用户使用指南

深入解析Debian与Ubuntu&#xff1a;技术特点与用户使用指南 引言 Debian和Ubuntu作为两大知名的Linux发行版&#xff0c;不仅在历史和理念上有所不同&#xff0c;在技术特点和用户使用方法上也各具特色。本文将深入解析它们的技术特点&#xff0c;并提供用户使用指南&#x…

GB/T28181规范解读和技术实现

GB/T28181发展历程 GB/T28181-2011&#xff1a; 提出与起草&#xff1a;由公安部科技信息化局提出&#xff0c;全国安全防范报警系统标准化技术委员会&#xff08;SAC/TC100&#xff09;归口&#xff0c;公安部一所等多家单位共同起草。发布与实施&#xff1a;2012 年 6 月 1 …

timedatectl命令:告别时间烦恼,一键同步系统时间

一、命令简介 ​timedatectl​ 命令用于查看和设置系统的时间和日期&#xff0c;以及配置时区和 NTP&#xff08;Network Time Protocol&#xff09;设置。 相关命令&#xff1a;cal ​显示日历、 date ​查看、设置日期 ‍ 二、命令参数 格式&#xff1a; timedatectl […

Linux基础(一):计算机组成

整体构成 五个部分&#xff1a;CPU、输入、输出、内存、硬盘 1.CPU 1.1CPU指令集 CPU内部包含一些微指令&#xff0c;包含两种——精简指令集&#xff08;Reduced Insruction Set Computer, RISC&#xff09;和复杂指令集&#xff08;Complex Instruction Set Computer, CIS…

基于ASRPRO的语音应答

做这个的起因是为了送女朋友&#xff0c;而且这东西本身很简单&#xff0c;所以在闲暇之余尝试了一下。 这个工程很简单&#xff0c;只通过对ASRPRO进行编程即可。 先看效果。&#xff08;没有展示所有效果&#xff0c;后续会列出来所有对话触发&#xff09; 语音助手示例1 语音…

全网最适合入门的面向对象编程教程:54 Python字符串与序列化-字符串格式化与format方法

全网最适合入门的面向对象编程教程&#xff1a;54 Python 字符串与序列化-字符串格式化与 format 方法 摘要&#xff1a; 在 Python 中&#xff0c;字符串格式化是将变量插入到字符串中的一种方式&#xff0c;Python 提供了多种字符串格式化的方法&#xff0c;包括旧式的 % 格…

解决iPhone无法有效响应问题的指南

当您触摸、滑动和点击屏幕时&#xff0c;iPhone 没有响应或屏幕冻结是很烦人的。不可否认&#xff0c;iPhone 是最好的智能手机之一&#xff0c;但它并不完美。触摸屏冻结是 iPhone 用户面临的最常见问题之一。 好消息是&#xff0c;这个问题通常是由软件错误而不是硬件损坏引…

MySQL的增删查改(基础)一

一.增 方式1&#xff08;简写插入&#xff09;&#xff1a; 语法&#xff1a;insert into 表名 values&#xff08;值&#xff0c;值&#xff0c;值……&#xff09;; 这里insert into 代表要插入一条新数据行&#xff0c;values后面就是该行的值&#xff0c;其中后面的值的…

C++20中头文件concepts的使用

<concepts>是C20中新增加的头文件&#xff0c;此头文件是concepts库的一部分&#xff0c;主要用于模板编程、泛型编程。包括 1.core language concepts&#xff1a; std::same_as&#xff1a;指定一种类型(type)与另一种类型是否相同。 std::derived_from&#xff1a;指定…

Apollo Planning2.0决策规划算法代码详细解析 (3):PlanningComponent框架介绍

Apollo Planning 2.0的框架更新涉及多个方面&#xff0c;这些更新旨在提升自动驾驶系统的灵活性、可扩展性和性能。 以下是Apollo Planning 2.0 的框架图&#xff1a; 其中&#xff0c;Apollo的PlanningComponent在自动驾驶系统中扮演着至关重要的角色。其主要作用可以归纳为以…

使用yum为centos系统安装软件以及使用(包含阿里云yum源配置)

centos系统配置阿里云yum源 因为centos7官方停止维护&#xff0c;自带yum源用不了了&#xff0c;所以可以更换成阿里云yum源 方法&#xff1a; 使用root权限执行以下语句 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo CentOS…

番外篇 | 复现AC-YOLOv5,进行自动化织物缺陷检测

前言:Hello大家好,我是小哥谈。我们提出了一种基于AC-YOLOv5的新型纺织缺陷检测方法。将空洞空间金字塔池化(ASPP)模块引入YOLOv5主干网络中,提出了squeeze-and-excitation(CSE)通道注意力模块,并将其引入到YOLOv5主干网络中。🌈 目录 🚀1.基础概念 🚀2.添…

一文上手Kafka【中】

一、发送消息细节 在发送消息的特别注意: 在版本 3.0 中&#xff0c;以前返回 ListenableFuture 的方法已更改为返回 CompletableFuture。为了便于迁移&#xff0c;2.9 版本添加了一个方法 usingCompletableFuture&#xff08;&#xff09;&#xff0c;该方法为 CompletableFu…

【韩顺平Java笔记】第2章:Java概述

按视频的标号来对应小标题&#xff0c;自用学习笔记 文章目录 5. 内容梳理6. 程序举例6.1 什么是程序 7. Java故事7.1 Java诞生小故事7.2 Java技术体系平台 8. Java特性8.1 Java重要特点 9. sublime10. jdk介绍10.1 Java运行机制及运行过程10.1.1 Java虚拟机&#xff08;JVM&a…

【Python】多个dataframe存入excel的不同的sheet表里,而不会被覆盖的方法

我发现&#xff0c;我原来用的多个工作簿存入的方法&#xff0c;发现不太可行&#xff0c;如果我用原来的方法&#xff0c;然后for循环&#xff0c;新的dataframe会把原来的覆盖掉&#xff0c;然后只剩下一个工作薄。原先的代码&#xff1a; with pd.ExcelWriter(file_name ) …

【题解】2022ICPC杭州-K

翻译 原题链接   简述一下就是每次询问重新定义一个字母排序表&#xff0c;问在这个顺序下n个字符串的序列的逆序数是多少。 字典树计算逆序数 先考虑初始状况下&#xff0c;即 a < b < . . . < z a<b<...<z a<b<...<z的情况下&#xff0c;逆序…