其他分享
首页 > 其他分享> > P1027 [NOIP2001 提高组] Car 的旅行路线

P1027 [NOIP2001 提高组] Car 的旅行路线

作者:互联网

P1027 [NOIP2001 提高组] Car 的旅行路线(计算几何 + Floyed最短路)

大致解题思路:

1、每个城市有四个点,N 个城市有4N个点,我们对这4N个点进行floyed,这就是我们最终的结果
2、根据三个点判断出第四个点的坐标:
3、通过坐标求距离:
4、因为每个点到其他点的旅行方式不一样,所以我们分情况判断花费,也可以说是dp数组的初始化:
5、对每个点进行floyed:
说一个当时写的时候犯的错误吧,是从A城市到达B城市,不是从序号A到序号B的城市,当时找了好长时间,后来重新读题才发现的这个问题。wtcl。。

详细解释如下:

1、每个城市有四个点,N 个城市有4N个点,我们对这4N个点进行floyed,这就是我们最终的结果
2、根据三个点判断出第四个点的坐标:
千万注意斜率不为零的情况分开讨论!!0不能做除数

void add(int cnt){
	int x1,x2,x3,y1,y2,y3;
	x1 = city[cnt-2].x;
	x2 = city[cnt-1].x;
	x3 = city[cnt].x;
	y1 = city[cnt-2].y;
	y2 = city[cnt-1].y;
	y3 = city[cnt].y;
	int k;
	int cx,cy;
	for(int i=1;i<=3;i++){
		if(i==1){
			if(x1==x2 && y1==y3){
				cx = x3-x1;
				city[++cnt].x = x2+cx;
				city[cnt].y = y2;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x1==x3 && y1==y2){
				cx = x2-x1;
				city[++cnt].x = x3+cx;
				city[cnt].y = y3;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x1==x2 || x1==x3) continue;
			k = ((y2-y1)*(y3-y1))/((x2-x1)*(x3-x1));
			if(k==-1){
				cx = x1-x2;
				cy = y1-y2;
				city[++cnt].x = x3-cx;
				city[cnt].y = y3-cy;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
		}
		else if(i==2){
			if(x2==x1 && y2==y3){
				cx = x3-x2;
				city[++cnt].x = x2+cx;
				city[cnt].y = y1;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x2==x3 && y2==y1){
				cx = x1-x2;
				city[++cnt].x = x2+cx;
				city[cnt].y = y3;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x2==x1||x2==x3) continue;
			k = ((y1-y2)*(y3-y2))/((x1-x2)*(x3-x2));
			if(k==-1){
				cx = x2-x1;
				cy = y2-y1;
				city[++cnt].x = x3-cx;
				city[cnt].y = y3-cy;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
		}
		else if(i==3){
			if(x3==x1 && y3==y2){
				cx = x2-x3;
				city[++cnt].x = x1+cx;
				city[cnt].y = y1;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x3==x2 && y3==y1){
				cx = x1-x3;
				city[++cnt].x = x2+cx;
				city[cnt].y = y2;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x3==x1 || x3==x2) continue;
			k = ((y1-y3)*(y2-y3))/((x1-x3)*(x2-x3));
			if(k==-1){
				cx = x3-x1;
				cy = y3-y1;
				city[++cnt].x = x2-cx;
				city[cnt].y = y2-cy;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
		}
	}
}

3、通过坐标求距离:

double dis(int a,int b){
	int x1 = city[a].x;
	int x2 = city[b].x;
	int y1 = city[a].y;
	int y2 = city[b].y;
	double ans = 0;
	ans = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
	return ans;
}

4、因为每个点到其他点的旅行方式不一样,所以我们分情况判断花费,也可以说是dp数组的初始化:

for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j) dp[i][j] = 0;
			else{
				if(city[i].num == city[j].num){
					dp[i][j] = dist[i][j] * sub[city[i].num];
				}
				else dp[i][j] = dist[i][j] * t;
			}
		}
	}

5、对每个点进行floyed:

for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]);
			}
		}
	}

说一个当时写的时候犯的错误吧,是从A城市到达B城市,不是从序号A到序号B的城市,当时找了好长时间,后来重新读题才发现的这个问题。wtcl。。

double ans = 0x7f7f7f7f;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(city[i].num==a&&city[j].num==b){
				ans = min(ans,dp[i][j]);
			}
		}
	}

完整代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn = 4010;
struct infor{//存放各个城市四个点的位置信息
	int x,y;
	int num;
}city[maxn];
int sub[maxn];//不同城市的地铁价格
int map[maxn][maxn];//当时为了找错误定义的数组,看看是不是构成了矩形
double dp[maxn][maxn];
double dist[maxn][maxn];//各个点之间的距离
void add(int cnt){//找第四个点的位置!!
	int x1,x2,x3,y1,y2,y3;
	x1 = city[cnt-2].x;
	x2 = city[cnt-1].x;
	x3 = city[cnt].x;
	y1 = city[cnt-2].y;
	y2 = city[cnt-1].y;
	y3 = city[cnt].y;
	int k;
	int cx,cy;
	for(int i=1;i<=3;i++){
		if(i==1){
			if(x1==x2 && y1==y3){
				cx = x3-x1;
				city[++cnt].x = x2+cx;
				city[cnt].y = y2;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x1==x3 && y1==y2){
				cx = x2-x1;
				city[++cnt].x = x3+cx;
				city[cnt].y = y3;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x1==x2 || x1==x3) continue;
			k = ((y2-y1)*(y3-y1))/((x2-x1)*(x3-x1));
			if(k==-1){
				cx = x1-x2;
				cy = y1-y2;
				city[++cnt].x = x3-cx;
				city[cnt].y = y3-cy;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
		}
		else if(i==2){
			if(x2==x1 && y2==y3){
				cx = x3-x2;
				city[++cnt].x = x2+cx;
				city[cnt].y = y1;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x2==x3 && y2==y1){
				cx = x1-x2;
				city[++cnt].x = x2+cx;
				city[cnt].y = y3;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x2==x1||x2==x3) continue;
			k = ((y1-y2)*(y3-y2))/((x1-x2)*(x3-x2));
			if(k==-1){
				cx = x2-x1;
				cy = y2-y1;
				city[++cnt].x = x3-cx;
				city[cnt].y = y3-cy;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
		}
		else if(i==3){
			if(x3==x1 && y3==y2){
				cx = x2-x3;
				city[++cnt].x = x1+cx;
				city[cnt].y = y1;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x3==x2 && y3==y1){
				cx = x1-x3;
				city[++cnt].x = x2+cx;
				city[cnt].y = y2;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
			else if(x3==x1 || x3==x2) continue;
			k = ((y1-y3)*(y2-y3))/((x1-x3)*(x2-x3));
			if(k==-1){
				cx = x3-x1;
				cy = y3-y1;
				city[++cnt].x = x2-cx;
				city[cnt].y = y2-cy;
				city[cnt].num = city[cnt-1].num;
				return ;
			}
		}
	}
}
double dis(int a,int b){
	int x1 = city[a].x;
	int x2 = city[b].x;
	int y1 = city[a].y;
	int y2 = city[b].y;
	double ans = 0;
	ans = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
	return ans;
}
double floyed(int n,int t,int a,int b){
	n = 4*n;
	for(int i=1;i<=4*n;i++){
		for(int j=1;j<=4*n;j++){
			dist[i][j] = dis(i,j);
		}
	}	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j) dp[i][j] = 0;
			else{
				if(city[i].num == city[j].num){
					dp[i][j] = dist[i][j] * sub[city[i].num];
				}
				else dp[i][j] = dist[i][j] * t;
			}
		}
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]);
			}
		}
	}
	double ans = 0x7f7f7f7f;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(city[i].num==a&&city[j].num==b){
				ans = min(ans,dp[i][j]);
			}
		}
	}
	return ans;
}
int main(){
	int T;
	cin >> T;
	while(T--){
		memset(sub,0,sizeof(sub));
		int n,t,a,b;
		int cnt = 1;
		cin >> n >> t >> a >> b;
		for(int i=1;i<=n;i++){
			cin >> city[cnt].x >> city[cnt].y;
			city[cnt++].num = i;
			cin >> city[cnt].x >> city[cnt].y;
			city[cnt++].num = i;
			cin >> city[cnt].x >> city[cnt].y;
			city[cnt].num = i;
			cin >> sub[i];
			add(cnt);
			cnt+=2;
		}
		memset(map,0,sizeof(map));
		for(int i=1;i<=cnt;i++){
			int x = city[i].x;
			int y = city[i].y;
			int num = city[i].num;
			map[x][y] = num;
		}
//		for(int i=1;i<=4*n;i++){
//			cout << city[i].x << " " << city[i].y << " " << city[i].num  << " " << sub[city[i].num]<< endl;
//		}
		double ans = floyed(n,t,a,b);
		printf("%.1lf\n",ans);
	}
	return 0;
}

标签:city,cnt,num,NOIP2001,int,Car,P1027,x2,x1
来源: https://blog.csdn.net/yingtingqi/article/details/113917887