首页 > 编程语言 >算法题之图论 [NOIP2001 提高组] Car的旅行路线详细题解

算法题之图论 [NOIP2001 提高组] Car的旅行路线详细题解

时间:2024-09-25 11:23:24浏览次数:3  
标签:City square NOIP2001 int 题解 include Car cities 第几个

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

这道题的思路呢,就是建个图,然后跑一遍Floyd,比较最小值就可以解决了。

but!它每个城市只给三个点(共四个),所以还得计算出第四个点坐标。这里根据矩形的中点公式来表示未知点的坐标:(这个思路源于大佬  _jimmywang_

                            

                       

勾股定理判断一下哪两个点构成对角线,然后就能求出这个点了。(具体代码在get_forth()函数)

由于建图把所有点都放一张二维表g[i][j],而一个城市有四个点,所以用 i,j通过除4或取余4的方案来表示第几个城市以及第几个城市的第几个点(具体代码在下面函数中)。

由于一个城市有4个点,如果单独设x,y坐标的话,感觉有点太麻烦,所以我采用了结构体的方式,记录每个城市的4个点和对应的单位行程花销。(并且用多个函数分步实现功能,逻辑比较清晰点

最后用floyd实现最小值的求取。

#include <iostream> 
#include <cmath>
#include <iomanip> 
using namespace std;
#define N 101
#define INF 999999999
struct City {
	int x[4],y[4];
	int price;
}; //把一个City的四个机场点都放一起
int s, t, A, B;
City cities[N];
double g[402][402], ans; // 邻接数组存储图,ans答案
int square(int n) {
	return n * n;
}
double pointDistance(int x1, int y1, int x2, int y2) {
	return sqrt(square(x1 - x2) + square(y1 - y2));
}
void get_forth(City& cities) {
	int ab = square(cities.x[0] - cities.x[1]) + square(cities.y[0] - cities.y[1]);
	int bc = square(cities.x[1] - cities.x[2]) + square(cities.y[1] - cities.y[2]);
	int ac = square(cities.x[0] - cities.x[2]) + square(cities.y[0] - cities.y[2]);
	if (ab + bc == ac) {
		cities.x[3] = cities.x[0] + cities.x[2] - cities.x[1];
		cities.y[3] = cities.y[0] + cities.y[2] - cities.y[1];
	}
	else if(ac + bc == ab){
		cities.x[3] = cities.x[0] + cities.x[1] - cities.x[2];
		cities.y[3] = cities.y[0] + cities.y[1] - cities.y[2];
	}
	else {
		cities.x[3] = cities.x[1] + cities.x[2] - cities.x[0];
		cities.y[3] = cities.y[1] + cities.y[2] - cities.y[0];
	}
}
void init_graph(int s) {
	for (int i = 1; i <= s; i++) {
		for (int j = 1; j <= s; j++) {
			if (i != j) {
				g[i][j] = INF;
			}
			else {
				g[i][j] = 0;
			}
		}
	}
	ans = INF;
	return ;
}
//求最短路 Floyd
//建图 需要一个比较大的二维数组来存储各边之间的长短
//此时已经记录了各个点之间的花销
void build_graph(int s,int t) {
	for (int i = 1; i <= s; i++) {
		for (int j = 1; j <= s; j++) {
			if (g[i][j] == INF) {
				int m1=i/4, n1=j/4;
				if (i % 4 != 0) {
					m1 += 1;
				}
				if (j % 4 != 0) {
					n1 += 1;
				}

				g[i][j] = t * sqrt(square(cities[m1].x[(i-1)%4] - cities[n1].x[(j-1)%4]) + square(cities[m1].y[(i - 1) % 4] - cities[n1].y[(j - 1) % 4]));
				g[j][i] = g[i][j];
			}
		}
	}
}
void inits(int s) {
	for (int i = 1; i <= s; i++) {
		for (int j = 0; j < 3; j++) {
			cin >> cities[i].x[j] >> cities[i].y[j];
		}
		cin >> cities[i].price;
		//第四个点需要计算出来
		get_forth(cities[i]);
		for (int n1 = 1; n1 <= 4; n1++) {
			for (int n2 = 1; n2 <= 4; n2++) {
				if(n1!=n2)
					g[4 * (i-1)+n1][4 * (i - 1) + n2] = cities[i].price * sqrt(square(cities[i].x[n1-1] - cities[i].x[n2-1]) + square(cities[i].y[n1-1] - cities[i].y[n2-1]));
			}
		}//计算四个点内的花销
		/*for (int ss = 0; ss < 4; ss++) {
			cout << cities[i].x[ss] <<"  "<< cities[i].y[ss] << endl;
		}*/
	}
	/*for (int i = 1; i <= 4 * s; i++) {
		for (int j = 1; j <= 4 * s; j++) {
			cout << setw(10) << g[i][j];
		}
		cout << endl;
	}
	cout << endl;
	*/
	return;
}
//利用Floyd算法进行最小化
double Floyd(int cnt,int A,int B){
	for (int k = 1; k <= cnt; k++)
		for (int i = 1; i <= cnt; i++)
			for (int j = 1; j <= cnt; j++)
				g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
	double mins = INF;
	int n, m;
	for (int i = 1; i <= 4; i++) {
		for (int j = 1; j <= 4; j++) {
			mins = min(mins, g[4 * (A-1) + i][j + 4 * (B-1)]);
			//cout << g[4 * (A - 1) + i][j + 4 * (B - 1)] << " ";
		}
		//cout << endl;
	}
	return mins;
}
int main() {
	int n;
	cin >> n;
	while (n--) {
		cin >> s >> t >> A >> B;
		init_graph(4 * s);
		inits(s); //初始化所有的飞机场坐标信息+建图
		build_graph(4 * s, t);
		
		/*for (int i = 1; i <= 4 * s; i++) {
			for (int j = 1; j <= 4 * s; j++) {
				cout << setw(10)<<g[i][j];
			}
			cout << endl;
		}*/
		cout <<fixed << setprecision(1) << Floyd(s * 4, A, B)<<endl;//setprecision(1)<<
	}
	return 0;
}

 美美(终于)过了

标签:City,square,NOIP2001,int,题解,include,Car,cities,第几个
From: https://blog.csdn.net/m0_73682715/article/details/142517954

相关文章

  • [ARC121E] Directed Tree 题解
    简单容斥题。思路题面的条件相当于一个位置上填的点不能是自己的祖先。发现直接做并不好做。考虑容斥。我们想要求出\(f_i\)为至少有\(i\)个不合法位置的方案数。那么答案为:\[\sum_{i=0}^nf_i(-1)^i\]如何求解。设\(f_{i,j}\)为\(i\)子树下有\(j\)个不合法位......
  • 2024-2025专题一题单 - 题解
    A-Virus原题链接题解B-Coverage原题链接题解C-Sensors原题链接题解D-MakeTakahashiHappy原题链接题解E-Don’tbecycle原题链接题解F-AlmostEqual原题链接题解G-StepUpRobot原题链接题解H-SnukeMaze原题链接题解I-MEX原题链接......
  • P5329 [SNOI2019] 字符串 题解
    Description给出一个长度为\(n\)的由小写字母组成的字符串\(a\),设其中第\(i\)个字符为\(a_i\(1\leqi\leqn)\)。设删掉第\(i\)个字符之后得到的字符串为\(s_i\),请按照字典序对\(s_1,s_2,……,s_n\)从小到大排序。若两个字符串相等,则认为编号小的字符串字典序更小。......
  • CF164D Minimum Diameter 题解
    最小点覆盖模板题。思路考虑二分直径\(x\)。我们将距离\(>x\)的点对连一条边,那么每一条边的两端至少有一端需要被删掉。这是最小点覆盖的定义。那么就是判断最小点覆盖是否小于等于\(k\)。发现这个问题并不好用一些多项式复杂度的做法解决。考虑暴搜。每一次我们把度......
  • CF2003F Turtle and Three Sequences 题解
    个人觉得*2800有点虚高。如果做过类似的题(比如[THUSCH2017]巧克力),应该可以想到随机映射,状压dp也不难想。实际上,看到要选出\(m\)种不同的颜色,且\(m\le5\)就可以想到将每种颜色随机映射到\(1\)到\(m\)中,这样子得出来的答案不会更优,而当答案选择的\(m\)种颜色恰好......
  • 20240924 模拟赛 T4 题解
    Description这是一道交互题。有一棵\(n\)个节点的树,现在要求你通过若干次询问得到这棵树的每一条边连接哪两个点。每次询问你需要指定\(n\)个整数\(d_1,d_2,\ldots,d_n\),满足\(-1\leqd_i\leqn\),其中\(1\leqi\leqn\)。每次询问交互库会返回给你一个长度为\(n\)的......
  • P4780 Phi的反函数 题解
    因为\(\varphi(x)\)的值只与\(x\)的不同质因子有关,又因为\(2^{31}\)之内的数的质因子个数不超过\(10\),所以容易枚举\(10\)个位置上填入的质因子打出朴素的暴力,简单剪枝后得到\(20\)分。注意需要先判掉\(x=n+1\)的情况。考虑优化:因为\(\varphi\)的值只与质因......
  • Codeforces Round 959 (Div. 1 + Div. 2) C. Hungry Games题解
    CodeforcesRound959(Div.1+Div.2)C.HungryGames题解题目链接大致题意:给定一个长度为n的数组,并且给出一对l,r表示一个区间,如果∑i......
  • 力扣题解2207
    大家好,欢迎来到无限大的频道。今日继续给大家带来力扣题解。题目描述(中等)​:字符串中最多数目的子序列给你一个下标从 0 开始的字符串 text 和另一个下标从 0 开始且长度为 2 的字符串 pattern ,两者都只包含小写英文字母。你可以在 text 中任意位置插入 一个......
  • 【洛谷】P2261 [CQOI2007] 余数求和 的题解
    【洛谷】P2261[CQOI2007]余数求和的题解洛谷传送门题解这还是蓝题,这还是省选qaq题目看着很简单,但是真的很考验思路,思路对了,代码不到555分钟写完。刚开始做的时......