PAT甲级1018留坑——第一个测试点未过(Dijikstar+Dfs)

题目分析:

主要是先进行狄杰斯特拉求出0点到每个点的最短路后用dfs求出所有的路径,将路径方案加入vector排序选择need最小和rest最小的方案,但是第一个测试却过不去,欢迎指正!!感谢!!

值得注意的是对于一条路径上的所有点进行调整的时候只能一步一步下来,后来多出的车不能用于调整前面走过的点的数量(很重要)

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<string.h>
  5 using namespace std;
  6 
  7 const int M = 0x3f3f3f3f;
  8 int c, n, sp, m;
  9 int mat[505][505];
 10 int vis[505];                        //第一次用于作为求dist记录该点是否到达 第二次用于深搜回溯记录是否走过该点
 11 int num[505];
 12 int dist[505];
 13 int les_dist = M;
 14 struct Node{
 15     int need;
 16     int rest;
 17     int distance;
 18     vector<int> road;
 19 };
 20 
 21 vector<Node> r;                        //用于存放多个最短路情况下的行走方案,一个数据结构存放一个方案的信息
 22 
 23 int minn(){
 24     int k = -1;
 25     int Min = M;
 26     int i;
 27     for(i = 1; i <= n; i++){
 28         if(vis[i] == 0 && dist[i] < Min){
 29             Min = dist[i];
 30             k = i;
 31         }
 32     }
 33     return k;
 34 }
 35 
 36 void run1(){
 37     int i;
 38     for(i = 0; i <= n; i++){        //将从0点开始到其他点的距离设为到该点的最小值
 39         dist[i] = mat[0][i];
 40     }    
 41     for(i = 1; i <= n; i++){        //包含0点则有n+1个点 需要进行n次查询
 42         int k = minn();                
 43         if(k == -1) break;            //查询次数未用完但k==-1则代表图不连通 退出循环
 44         vis[k] = 1;
 45         int j;
 46         for(j = 1; j <= n; j++){
 47             if(vis[j] == 0 && dist[k] + mat[k][j] < dist[j]){
 48                 dist[j] = dist[k] + mat[k][j];
 49             }
 50         }
 51     }
 52     les_dist = dist[sp];            //全局变量les_dist存放到达终点的最短路径
 53 }
 54 
 55 void dfs(Node s, int x){
 56     //对于当前点x来说 需要判断此时存放路径数据的长度加到达x的长度和最短路径长度的关系
 57     int pre = s.road.back();    //前一个点
 58     if(s.distance + mat[pre][x] <= les_dist){        
 59         s.distance += mat[pre][x];
 60         if(num[x] < c/2){        //需要对该点的自行车的数量进行调整
 61             if(s.rest >= c/2 - num[x]){
 62                 s.rest -= (c/2 - num[x]);
 63             }else{                //剩余的不够 
 64                 s.need += c/2 - num[x] - s.rest;    //需要的总数减去有的总数则为需要从0点发出的数量
 65                 s.rest = 0; 
 66             }
 67         }else if(num[x] > c/2){
 68             s.rest += num[x] - c/2;    //对多余的车都放入rest中 
 69         }
 70         s.road.push_back(x);    //将x加入已经走过的点的队列 
 71         //当点加完之后判断是否到了终点
 72         if(x == sp){
 73             r.push_back(s);        //将s这个路径选择方案加入vector r 
 74         } 
 75     }
 76     if(sp == x) return;
 77     vis[x] = 1;
 78     int i;
 79     for(i = 1; i <= n; i++){
 80         if(vis[i] == 0 && mat[x][i] != M){
 81             dfs(s, i);
 82             vis[i] = 0;
 83         }        
 84     }
 85 }
 86 
 87 bool cmp(Node a, Node b){
 88     if(a.need != b.need) a.need < b.need;
 89     else{
 90         return a.rest < b.rest;
 91     }
 92 }
 93 
 94 void run2(){
 95     memset(vis, 0, sizeof(vis));    //此次的vis需要重新清零
 96     Node s;
 97     s.need = 0;
 98     s.rest = 0;
 99     s.distance = 0;
100     s.road.push_back(0);            //将0点作为起始点 
101     dfs(s, 0);                        //从0点开始 其中s为当前存放路径数据的数据结构
102     sort(r.begin(), r.end(), cmp); 
103     Node ans = r.front();
104     if(sp != 0){
105         printf("%d ", ans.need);
106         int i;
107         for(i = 0; i < ans.road.size(); i++){
108             if(i != 0) printf("->");
109             printf("%d", ans.road[i]);
110         }
111         printf(" %d\n", ans.rest);
112     }else{
113         printf("0 0 0\n");
114     }
115 }
116 
117 int main(){
118     scanf("%d%d%d%d", &c, &n, &sp, &m);
119     memset(mat, M, sizeof(mat));
120     memset(vis, 0, sizeof(vis));
121     int i;
122     for(i = 1; i <= n; i++){        //输入没个点的自行车数量
123         scanf("%d", &num[i]);
124     }
125     for(i = 0; i < m; i++){
126         int x, y, z;
127         scanf("%d%d%d", &x, &y, &z);
128         mat[x][y] = z;
129         mat[y][x] = z;
130     }    
131     run1();                            //这部分完成了从起点到sp点的最短路径的计算
132     run2();                            //通过bfs查询出通路然后加入vector
133     return 0;
134 }

 

posted on 2019-10-29 16:40  白泽talk  阅读(394)  评论(2编辑  收藏  举报