码迷,mamicode.com
首页 > 其他好文 > 详细

Floyd-例题-实现-我的第一篇博客

时间:2020-03-12 09:17:50      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:通过   ace   优先   mit   strong   除了   题目   疑问   方向   

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. 如何找到“最短”--的表示方式,最短可能有多种情况,可能有多个条件,像这题有多个因素变量,是否有优先权,是否在这之前需要贪心或者先排序操作。
  2. 路径的初始化问题,其他参数的初始化问题,需不需要中间变量做桥梁***
  3. 有了最短路的定义,该怎么操作“更新”也是个难题。本题的难点就在于更新——不同路径繁华度最大值总是会变,每次找到一条新路都需要检查和更新。
  4. 这一环也是最容易出现问题的一环——常见问题:
    • 更新的对象,找错/找漏(我一开始的问题)
    • 更新的办法有问题,不全面,更新的操作不全,需要分类讨论
    • 更新的时候没有考虑到连锁影响,是否需要回溯或者重来
    • 更新直接操作复杂,需要找中间桥梁+中间补充操作——原博主的办法
  5. 最短路只是题目中的一环,在这基础上还有别的算法需要综合使用。

对于这个问题,原博主使用的方式是贪心排序繁华度,除了繁华度,最短路的数组,另外又找了一个数组代替最终消费,然后每次都用通过排序直接对应新繁华度代替,

你会发现如果连续使用最短路,更新结果会变。因为更新是不统一的。(个人对原博主的解法还有疑问,以后再做补充)

而我的办法比较老土,就是简单的模拟,繁华度另开一个数组,每次把原来的繁华度减掉,然后加上新的繁华度,从而得到最短,这个结果是不会变的。

 

  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<<"!\t";
 60                         else cout<<a[i][j]<<"\t";
 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-例题-实现-我的第一篇博客

标签:通过   ace   优先   mit   strong   除了   题目   疑问   方向   

原文地址:https://www.cnblogs.com/KID-yln/p/12466887.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!