Floyd-例题-实现-我的第一篇博客
Posted kid-yln
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Floyd-例题-实现-我的第一篇博客相关的知识,希望对你有一定的参考价值。
https://www.cnblogs.com/lbssxz/p/11014911.html
这是网上看到的题目,以上是原博主的解答和题目来源(没找到别的题目来源)
题目大意:
城市交通费
【问题描述】
有 n 个城市,编号 1~n。其中 i 号城市的繁华度为 pi。省内有 m 条可以双向同行的高速
公路,编号 1~m。编号为 j 的高速公路连接编号为 aj 和 bj 两个城市,经过高速公路的费用
是 wj。若从城市 x 出发到某城市 y,除了需要缴纳高速公路费用,还要缴纳“城市建设费”
(为从 x 城市到 y 城市所经过的所有城市中繁华度的最大值,包括 x 和 y 在内)。
现提出 q 个询问,每个询问给出一组 x 和 y,你需要回答从 x 出发到 y 城市,所需要的
最低交通费(高速公路费+城市建设费)是多少。
【输入】
第一行三个整数 n,m,q。
第二行 n 个整数,表示 p1~pn。
接下来 m 行中,每行 3 个正整数,第 j 行包含 Aj,Bj,Wj。
随后 Q 行每组两个正整数 x,y 表示一组询问。
【输出】
共 Q 行,为对 Q 个问题的回答:x 城市到 y 城市的最小交通费用。
【样例输入】
5 7 2
2 5 3 3 4
1 2 3
1 3 2
2 5 3
5 3 1
5 4 1
2 4 3
3 4 4
1 4
2 3
【样例输出】
8
9
【数据范围及约定】
n≤250,m≤20000,Q≤10000,Pi≤10000,Wj≤2000,保证任意两个城市可以互相到达。
------------恢复内容结束------------
显然这是一个最短路问题,但是即便是最短路,即便确定了思路是FLOYD,仍然有很多不一样的思路。以下为我的思路和原本错误的方向——更新的对象错误。
很多最短路问题,出了模板题以外,难点就在于:
- 如何找到“最短”--的表示方式,最短可能有多种情况,可能有多个条件,像这题有多个因素变量,是否有优先权,是否在这之前需要贪心或者先排序操作。
- 路径的初始化问题,其他参数的初始化问题,需不需要中间变量做桥梁***
- 有了最短路的定义,该怎么操作“更新”也是个难题。本题的难点就在于更新——不同路径繁华度最大值总是会变,每次找到一条新路都需要检查和更新。 这一环也是最容易出现问题的一环——常见问题:
- 更新的对象,找错/找漏(我一开始的问题)
- 更新的办法有问题,不全面,更新的操作不全,需要分类讨论
- 更新的时候没有考虑到连锁影响,是否需要回溯或者重来
- 更新直接操作复杂,需要找中间桥梁+中间补充操作——原博主的办法
- 最短路只是题目中的一环,在这基础上还有别的算法需要综合使用。
对于这个问题,原博主使用的方式是贪心排序繁华度,除了繁华度,最短路的数组,另外又找了一个数组代替最终消费,然后每次都用通过排序直接对应新繁华度代替,
你会发现如果连续使用最短路,更新结果会变。因为更新是不统一的。(个人对原博主的解法还有疑问,以后再做补充)
而我的办法比较老土,就是简单的模拟,繁华度另开一个数组,每次把原来的繁华度减掉,然后加上新的繁华度,从而得到最短,这个结果是不会变的。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <cstring> 6 #include <string> 7 #include <limits.h> 8 using namespace std; 9 typedef long long ll; 10 const ll INF = 0x3f3f3f3f3f3f3f3fLL; 11 int a[255][255]; 12 int n=0; 13 const int I=0x3f3f3f3f; 14 int m=0; 15 int q=0; 16 int t[255]; 17 int p[255][255];//表示当前的最大繁华度 18 void floy0() { 19 //memset(a,0,sizeof(a)); 20 21 for(int k=1; k<=n; k++) { 22 for(int j=1; j<=n; j++) { 23 for(int i=1; i<=n; i++) { 24 /* 25 int d1=max(t[i],t[j]); 26 int d2=max(t[i],t[j]); 27 d2=max(d2,t[k]); 28 a[i][j]=a[j][i]=min(a[j][i]+d1,d2+a[j][k]+a[k][i]);*/ 29 //上面这个式子错误在于,不是每次都加一次繁华度. 30 //而是最后得到ij之后加一次繁华度,每次应该更新这个繁华度 31 //更新的时候一减一加 32 //或者从一开始就从繁华度最大值最小优先筛选--排序贪心一次后再做 33 //存在更新不完全??? 34 int l=0; 35 if(a[j][k]<I&&a[k][i]<I&&p[i][k]<I&&p[j][k]<I) { 36 if(a[i][j]<I) { 37 l=max(p[j][k],p[i][k]); 38 if(a[j][i]>((a[j][k]-p[j][k])+(a[k][i]-p[k][i])+l)) { 39 a[j][i]=(a[j][k]-p[j][k])+(a[k][i]-p[k][i])+l; 40 p[i][j]=p[j][i]=l; 41 cout<<j<<"-->"<<i<<": "<<j<<"-->"<<k<<"-->"<<i<<endl<<endl; 42 } 43 44 45 } else { 46 l=max(p[k][i],p[j][k]); 47 p[i][j]=p[j][i]=l; 48 a[i][j]=a[j][i]=(a[j][k]-p[j][k])+(a[k][i]-p[k][i])+l; 49 cout<<j<<"-->"<<i<<": "<<j<<"-->"<<k<<"-->"<<i<<endl<<endl; 50 } 51 52 } 53 54 //比较的是最短路净值所以后面那个式子里的每个减完再加 55 56 57 for(int i=1; i<=n; i++) { 58 for(int j=1; j<=n; j++) { 59 if(a[i][j]>=I||a[i][j]<0)cout<<"! "; 60 else cout<<a[i][j]<<" "; 61 } 62 puts(""); 63 } 64 puts(""); 65 66 } 67 } 68 69 } 70 71 72 73 } 74 75 76 int main () { 77 78 79 scanf("%d%d%d",&n,&m,&q); 80 81 memset(t,0,sizeof(t)); 82 memset(a,I,sizeof(a)); 83 memset(p,I,sizeof(p)); 84 for(int i=1; i<=n; i++) { 85 scanf("%d",&t[i]); 86 a[i][i]=t[i]; 87 p[i][i]=t[i]; 88 } 89 while(m--) { 90 int i,j,w; 91 scanf("%d%d%d",&i,&j,&w); 92 p[i][j]=p[j][i]=max(t[i],t[j]); 93 a[i][j]=a[j][i]=w+p[i][j]; 94 95 } 96 97 puts(""); 98 floy0(); 99 return 0; 100 }
以上是关于Floyd-例题-实现-我的第一篇博客的主要内容,如果未能解决你的问题,请参考以下文章