赞
踩
L3-011 直捣黄龙 (30 分)
本题是一部战争大片 —— 你需要从己方大本营出发,一路攻城略地杀到敌方大本营。首先时间就是生命,所以你必须选择合适的路径,以最快的速度占领敌方大本营。当这样的路径不唯一时,要求选择可以沿途解放最多城镇的路径。若这样的路径也不唯一,则选择可以有效杀伤最多敌军的路径。
输入第一行给出 2 个正整数 N(2 ≤ N ≤ 200,城镇总数)和 K(城镇间道路条数),以及己方大本营和敌方大本营的代号。随后 N-1 行,每行给出除了己方大本营外的一个城镇的代号和驻守的敌军数量,其间以空格分隔。再后面有 K 行,每行按格式城镇1 城镇2 距离
给出两个城镇之间道路的长度。这里设每个城镇(包括双方大本营)的代号是由 3 个大写英文字母组成的字符串。
按照题目要求找到最合适的进攻路径(题目保证速度最快、解放最多、杀伤最强的路径是唯一的),并在第一行按照格式己方大本营->城镇1->...->敌方大本营
输出。第二行顺序输出最快进攻路径的条数、最短进攻距离、歼敌总数,其间以 1 个空格分隔,行首尾不得有多余空格。
- 10 12 PAT DBY
- DBY 100
- PTA 20
- PDS 90
- PMS 40
- TAP 50
- ATP 200
- LNN 80
- LAO 30
- LON 70
- PAT PTA 10
- PAT PMS 10
- PAT ATP 20
- PAT LNN 10
- LNN LAO 10
- LAO LON 10
- LON DBY 10
- PMS TAP 10
- TAP DBY 10
- DBY PDS 10
- PDS PTA 10
- DBY ATP 10

- PAT->PTA->PDS->DBY
- 3 30 210
作者: 陈越
单位: 浙江大学
时间限制: 150 ms
内存限制: 64 MB
代码长度限制: 16 KB
这道题是基础的最短路算法加一些限制条件,代码用的SPFA算法。输入数据的城市编号是字符串,用map映射成整数就可以去存边,跑最短路了。
求最短路时
if(dist[v]>dist[u]+fee) 这时就直接更新到城市v的最短距离了;
path[v]=u; 记录到城市v的最短路径中v的上一个城市是谁;
town[v]=town[u]+1; town数组记录到城市v的最短路中最多可以解放多少城市(就是整个路径经过多少个城市);
shadi[v]=shadi[u]+army[v]; 数组shadi记录通过最短路到城市v最多可以杀敌多少;
lushu[v]=lushu[u]; 数组lushu记录最短距离相同的路径有几条;
开始WA了无数发就是因为不知道咋想的把最短路被更新时lushu[v]从1开始重新计数,写了个lushu[v]=1,然后错错错
- #include <bits/stdc++.h>
- #define INF 1234123411
- using namespace std;
-
- int N,M,K,cnt,shu,zuiduan;
- int army[210];//army[i]记录城市i有多少敌军
- int dist[210];//记录从源点到每个城市的最短距离
- int path[210];//path[i]=j记录到城市i的最短路径中,上一步是从j走到i的
- int town[210];//town[i]记录通过最短路到城市i时,沿途最多解放了多少城市(其实就是经过了多少)
- int shadi[210];//shadi[i]表示通过最短路到城市i时,一共杀敌多少
- int res[210];//输出路径时用到
- int lushu[210];//最短路可能不止一条,lushu[i]表示到城市i最短距离相同的路径有几条
- bool vis[210];
- vector<struct data>G[210];//存边建图
- map<string,int>Q;//输入的城市编号是字符串,映射成整数
- map<int,string>P;
- string tou,wei,ch,s1,s2;
-
- struct data
- {
- int to;
- int cost;
- };
-
- void SPFA(int s)
- {
- for(int i=0;i<210;i++)dist[i]=INF;
- dist[s]=0;
- lushu[s]=1;
- queue<int> qwq;
- qwq.push(s);
- vis[s]=1;
-
- while(!qwq.empty())
- {
- int u=qwq.front();
- qwq.pop();
- vis[u]=0;
-
- for(int i=0;i<int(G[u].size());i++)
- {
- bool sign=false;
- int v=G[u][i].to;
- int fee=G[u][i].cost;
- if(dist[v]>dist[u]+fee)
- {
- sign=true;
- dist[v]=dist[u]+fee;//更新到v的最短距离
- path[v]=u;//到v的最短路中上一步是从城市u走到v的
- town[v]=town[u]+1;//到v最多可以解放的城市数量
- shadi[v]=shadi[u]+army[v];//到v最多可以杀敌的数量
- lushu[v]=lushu[u];//既然现在更新的最短路是上一步是从u走到v的,
- //那么到u的最短路有几条,到v的最短路也有几条
- //就是在这里一开始简单的写成lushu[v]=1;导致30分只得25分
- }
- else if(dist[v]==dist[u]+fee)
- {
- if(town[v]<town[u]+1)
- {
- path[v]=u;
- town[v]=town[u]+1;
- shadi[v]=shadi[u]+army[v];
- }
- else if(town[v]==town[u]+1)
- {
- if(shadi[v]<shadi[u]+army[v])
- {
- path[v]=u;
- shadi[v]=shadi[u]+army[v];
- }
- }
- lushu[v]+=lushu[u];//在else if这部分内容如果执行的话说明从源点经过u到v的距离
- //不能更新到v的最短距离值更小,但是值相同到v的最短路数量就增加了lushu[v]应该累
- //加lushu[u],一开始写的lushu[v]++,错到身心俱疲
- }
- if(sign)
- {
- if(vis[v]==0)
- {
- qwq.push(v);
- vis[v]=1;
- }
- }
- }
-
- }
- }
-
- int main()
- {
- cnt=0;
- cin>>N>>K>>tou>>wei;
- Q[tou]=1;
- P[1]=tou;
- for(int i=2;i<=N;i++)
- {
- cin>>ch>>army[i];
- Q[ch]=i;
- P[i]=ch;
- }
- while(K--)
- {
- cin>>s1>>s2>>shu;
- G[Q[s1]].push_back(data{Q[s2],shu});
- G[Q[s2]].push_back(data{Q[s1],shu});
- }
- SPFA(1);
-
- //存路径时path[]数组是倒着存路径关系的,比如1->3->7 path数组存的是path[7]=3;path[3]=1
- //下面用while循环把路径存到res[]数组里,倒着输出这一串数字刚好是正向的路径
- int jieshu=Q[wei];
- while(jieshu!=0)
- {
- res[++cnt]=jieshu;
- jieshu=path[jieshu];
- }
- for(int i=cnt;i>=1;i--)
- {
- cout<<P[res[i]];
- if(i==1)cout<<endl;
- else cout<<"->";
- }
- cout<<lushu[Q[wei]]<<" "<<dist[Q[wei]]<<" "<<shadi[Q[wei]]<<endl;
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。