程序设计思维与实践 Week7 作业

A - TT 的魔法猫

题目描述

众所周知,TT 有一只魔法猫。

这一天,TT 正在专心致志地玩《猫和老鼠》游戏,然而比赛还没开始,聪明的魔法猫便告诉了 TT 比赛的最终结果。TT 非常诧异,不仅诧异于他的小猫咪居然会说话,更诧异于这可爱的小不点为何有如此魔力?

魔法猫告诉 TT,它其实拥有一张游戏胜负表,上面有 N 个人以及 M 个胜负关系,每个胜负关系为 A B,表示 A 能胜过 B,且胜负关系具有传递性。即 A 胜过 B,B 胜过 C,则 A 也能胜过 C。

TT 不相信他的小猫咪什么比赛都能预测,因此他想知道有多少对选手的胜负无法预先得知,你能帮帮他吗?

  • 第一行给出数据组数。

每组数据第一行给出 N 和 M(N , M <= 500)。

接下来 M 行,每行给出 A B,表示 A 可以胜过 B。

  1. 对于每一组数据,判断有多少场比赛的胜负不能预先得知。注意 (a, b) 与 (b, a) 等价,即每一个二元组只被计算一次。
  2. input
    3
    3 3
    1 2
    1 3
    2 3
    3 2
    1 2
    2 3
    4 2
    1 2
    3 4
  3. output
    0
    0
    4

分析

  1. 这道题所有的猫猫构成一个图,猫的胜负关系构成一个有向边,可以计算所有有向边的闭包,并且用数组记录,使用弗洛伊德算法,将所有的路径得出结果
  2. 单纯使用弗洛伊德算法由于o(n^3)的复杂度,会超时,所以我们要考虑剪枝,思考在弗洛伊德算法当中,当第一次枚举,如果如果对于i和k这条边没有有向边,则下一个枚举点j就没有必要了,因为永远不可能修改j,k边,

代码

#include<iostream>
#include<cstring>
using namespace std;
const int maxn=5E2+10;
int gra[maxn][maxn];
int m,n,tmp;
int main(){
	int num,op1,op2;scanf("%d",&num);
	while(num--){
		int ans=0;
		memset(gra,0,sizeof(gra));
		scanf("%d%d",&n,&m);
		for(int i=0;i<m;i++){
			scanf("%d%d",&op1,&op2);
			gra[op1][op2]=1;
			gra[op2][op1]=-1;
		}
		for(int k=1;k<=n;k++){
			for(int i=1;i<n;++i){
				if(i==k||!gra[i][k]) continue;
				for(int j=i+1;j<=n;j++){
					if(j==k) continue;
					if(!gra[i][j]&&(gra[i][k]*gra[k][j])>0){
						gra[i][j]=gra[i][k];gra[j][i]=-gra[i][k];
						//printf("%d,%d\n",i,j);
					}
				}
			}
		}
		for(int i=1;i<n;i++){
			for(int j=i+1;j<=n;j++)
				if(!gra[i][j]) ++ans;
		}
		printf("%d\n",ans);
	}
}

B - TT 的旅行日记

题目描述

众所周知,TT 有一只魔法猫。
今天他在 B 站上开启了一次旅行直播,记录他与魔法猫在喵星旅游时的奇遇。 TT 从家里出发,准备乘坐猫猫快线前往喵星机场。猫猫快线分为经济线和商业线两种,它们的速度与价钱都不同。当然啦,商业线要比经济线贵,TT 平常只能坐经济线,但是今天 TT 的魔法猫变出了一张商业线车票,可以坐一站商业线。假设 TT 换乘的时间忽略不计,请你帮 TT 找到一条去喵星机场最快的线路,不然就要误机了!

  • 输入包含多组数据。每组数据第一行为 3 个整数 N, S 和 E (2 ≤ N ≤ 500, 1 ≤ S, E ≤ 100),即猫猫快线中的车站总数,起点和终点(即喵星机场所在站)编号。
    

    下一行包含一个整数 M (1 ≤ M ≤ 1000),即经济线的路段条数。

    接下来有 M 行,每行 3 个整数 X, Y, Z (1 ≤ X, Y ≤ N, 1 ≤ Z ≤ 100),表示 TT 可以乘坐经济线在车站 X 和车站 Y 之间往返,其中单程需要 Z 分钟。

    下一行为商业线的路段条数 K (1 ≤ K ≤ 1000)。

    接下来 K 行是商业线路段的描述,格式同经济线。

    所有路段都是双向的,但有可能必须使用商业车票才能到达机场。保证最优解唯一。

  • 对于每组数据,输出3行。第一行按访问顺序给出 TT 经过的各个车站(包括起点和终点),第二行是 TT 换乘商业线的车站编号(如果没有使用商业线车票,输出"Ticket Not Used",不含引号),第三行是 TT 前往喵星机场花费的总时间。
    本题不忽略多余的空格和制表符,且每一组答案间要输出一个换行

  • input
    4 1 4
    4
    1 2 2
    1 3 3
    2 4 4
    3 4 5
    1
    2 4 3

  • output
    1 2 4
    2
    5

题意分析

  1. 这道题我是采用第一个思路,即列举从头和尾进行迪杰科斯拉算法,计算所有的点到两头的最短距离,然后,一一列举所有的特殊路径(a,b),计算所有的路径的头和尾的距离之和和反制的距离之和,取最小的并且记录,计算所有的特殊路径的最短长度,和不使用的最短路径比较就可以
  2. 对于路径的求取,是使用两个数组分别记录在dij算法中的走向,之后需要的时候,从尾部开始遍历到头,记录所有经过的节点就可以

代码

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int nmax=1E3+10;
const int mmax=2E3+10;
const int inf=1E9;
//链式前向星
struct edge{
	int to,next,w;
}e1[mmax];
int head[nmax],tot=1;
void add(int x,int y,int w){
	e1[++tot].to=y,e1[tot].w=w;
	e1[tot].next=head[x],head[x]=tot;
}
//
int dis1[nmax],dis2[nmax],vis[nmax],pre1[nmax],pre2[nmax];
int n,s,e,edge1,edge2;
void init(int d[],int pre[]){for(int i=0;i<=n;i++){d[i]=inf,vis[i]=0,pre[i]=0;}}
void dij(int st,int dis[],int pre[]){
	init(dis,pre);
	priority_queue<pair<int,int> > que;
	que.push(make_pair(0,st));dis[st]=0;
	while(!que.empty()){
		int x=que.top().second;que.pop();
		if(vis[x]) continue;
		vis[x]=1;
		for(int i=head[x];i;i=e1[i].next){
			if(!vis[e1[i].to]&&dis[e1[i].to]>dis[x]+e1[i].w){
				pre[e1[i].to]=x;
				dis[e1[i].to]=dis[x]+e1[i].w;
				que.push(make_pair(-dis[e1[i].to],e1[i].to));
			}
		}
	}
}
void output(int pre[],int pos,int end){
	if(pos==end) {printf("%d ",pos);return ;}
	output(pre,pre[pos],end);
	printf("%d ",pos);
}
int main(){
        bool flag=true;
	while(~scanf("%d%d%d",&n,&s,&e)){
                if(!flag) printf("\n");
                else flag=false;
 		memset(head,0,sizeof(head));
		tot=1;
		scanf("%d",&edge1);
		for(int i=0;i<edge1;++i){int a,b,c;scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);}
		dij(s,dis1,pre1);
		dij(e,dis2,pre2);
		scanf("%d",&edge2);
		int now=dis1[e],b1,b2;
	//for(int i=1;i<=n;i++) printf("%d  ",dis1[i]);
		for(int i=0;i<edge2;++i){
			int a,b,c;scanf("%d%d%d",&a,&b,&c);
			if(dis1[a]+dis2[b]>dis1[b]+dis2[a]) swap(a,b);
			if(dis1[a]+dis2[b]+c<now){
				b1=a,b2=b;
				now=dis1[a]+dis2[b]+c;
			}
		}
	//printf("|%d|\n",now);
		if(now==dis1[e]){
			vector<int> res;
			int pos=s;
			while(pos){
				res.push_back(pos);
				pos=pre2[pos];
			}
			for(int i=0;i<res.size();i++) printf(i==0?"%d":" %d",res[i]);
			printf("\nTicket Not Used\n%d\n",now);
		}
		else {
			/*output(pre1,b1,s);
			int pos=b2;
			while(pos!=e){
				printf("%d ",pos);
				pos=pre2[pos];
			}
			printf("%d\n",e);*/
			int pos=b1;
			vector<int> res;
			while(pos){
				res.push_back(pos);
				pos=pre1[pos];
			}
			reverse(res.begin(),res.end());
			pos=b2;
			while(pos){
				res.push_back(pos);
				pos=pre2[pos];
			}
			for(int i=0;i<res.size();i++) printf(i==0?"%d":" %d",res[i]);
			printf("\n%d\n%d\n",b1,now);
		}
	}
	return 0;
}

C - TT 的美梦

题目描述

这一晚,TT 做了个美梦!

在梦中,TT 的愿望成真了,他成为了喵星的统领!喵星上有 N 个商业城市,编号 1 ~ N,其中 1 号城市是 TT 所在的城市,即首都。

喵星上共有 M 条有向道路供商业城市相互往来。但是随着喵星商业的日渐繁荣,有些道路变得非常拥挤。正在 TT 为之苦恼之时,他的魔法小猫咪提出了一个解决方案!TT 欣然接受并针对该方案颁布了一项新的政策。

具体政策如下:对每一个商业城市标记一个正整数,表示其繁荣程度,当每一只喵沿道路从一个商业城市走到另一个商业城市时,TT 都会收取它们(目的地繁荣程度 - 出发地繁荣程度)^ 3 的税。

TT 打算测试一下这项政策是否合理,因此他想知道从首都出发,走到其他城市至少要交多少的税,如果总金额小于 3 或者无法到达请悄咪咪地打出 ‘?’。

  • 第一行输入 T,表明共有 T 组数据。(1 <= T <= 50)
    对于每一组数据,第一行输入 N,表示点的个数。(1 <= N <= 200)
    第二行输入 N 个整数,表示 1 ~ N 点的权值 a[i]。(0 <= a[i] <= 20)
    第三行输入 M,表示有向道路的条数。(0 <= M <= 100000)
    接下来 M 行,每行有两个整数 A B,表示存在一条 A 到 B 的有向道路。
    接下来给出一个整数 Q,表示询问个数。(0 <= Q <= 100000)
    每一次询问给出一个 P,表示求 1 号点到 P 号点的最少税费。
  • 每个询问输出一行,如果不可达或税费小于 3 则输出 ‘?’。
  • input
  • 2
    5
    6 7 8 9 10
    6
    1 2
    2 3
    3 4
    1 5
    5 4
    4 5
    2
    4
    5
    10
    1 2 4 4 5 6 7 8 9 10
    10
    1 2
    2 3
    3 1
    1 4
    4 5
    5 6
    6 7
    7 8
    8 9
    9 10
    2
    3 10
  • output
    Case 1:
    3
    4
    Case 2:
    ?
    ?

题意分析

这道题就是考察最短路径的题目,并且题中有负环的可能,所以要使用spfa算法来进行处理使用cnt数组来记录到某个点的路径的长度,如果使用长度超过了最长的长度,就证明出现了负环,那么负环上的点,以及负环能够到达的所有的点,我们都不能够计算他们的长度,所以我们就给他们标记上负无穷的可到长度使用bfs来搜索他到的点,得到所有的路径的距离,根据题目给的输出格式进行输出就可以了

代码

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int nmax=2E2+10;
const int inf=1E9;
const int NO=1E9+2;
vector<pair<int,int> > edge[nmax];
int a[nmax],inq[nmax],dis[nmax],cnt[nmax];
int n,m,q,op1,op2;
void init(){for(int i=1;i<=n;++i){inq[i]=0,cnt[i]=0;dis[i]=inf;}}
int get_p(int x,int y){ int t=a[x]-a[y];return t*t*t;}
/*void dfs(int ss){
	if(dis[ss]==0) return ;
	dis[ss]=0;
	for(auto iter=edge[ss].begin();iter!=edge[ss].end();iter++){
		dfs(iter->second);
	}
}*/
void bfs(int ss){
	queue<int> quu;
	if(dis[ss]==-inf) return;
	quu.push(ss);
	while(!quu.empty()){
		int x=quu.front();quu.pop();
		for(auto iter=edge[x].begin();iter!=edge[x].end();++iter){
			if(dis[iter->second]!=-inf){
				dis[iter->second]=-inf;
				quu.push(iter->second);
			}
		}
	}
}
void spfa(){
	queue<int> que;
	init();
	que.push(1);
	inq[1]=1,dis[1]=0;
	while(!que.empty()){
		int x=que.front();que.pop();inq[x]=0;
		for(auto iter=edge[x].begin();iter!=edge[x].end();iter++){
			int wei=get_p(iter->second,x);
			if(dis[iter->second]>dis[x]+wei){
				cnt[iter->second]=cnt[x]+1;
				if(cnt[iter->second]>=n) {bfs(x);continue;}
				dis[iter->second]=dis[x]+wei;
				if(!inq[iter->second]){ inq[iter->second]=1;que.push(iter->second);}
			}
		}
	}
}
int main(){
	int num;scanf("%d",&num);
	for(int p=1;p<=num;p++){
		scanf("%d",&n);
		for(int i=1;i<=n;++i) {scanf("%d",a+i);edge[i].clear();}
		scanf("%d",&m);
		for(int i=1;i<=m;i++) {scanf("%d%d",&op1,&op2);edge[op1].push_back(make_pair(op1,op2));}
		spfa();
		printf("Case %d:\n",p);
		scanf("%d",&q);
		
		for(int i=0;i<q;i++){
			int tmp;scanf("%d",&tmp);
			if(dis[tmp]<3||dis[tmp]==inf) printf("?\n");
			else printf("%d\n",dis[tmp]);
		}
			}
}
在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值