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

【思路】
早上刚刚把迪杰斯特拉算法彻底弄清楚,马上做一道题来温习一下。这道题思路其实非常简单,就是迪杰斯特拉算法求最短路径,然后在这个基础上,用一些数组存储一些中间状态信息就行了。虽然思路简单,但实现起来还是相当复杂的,图论中的数据结构本身就已经非常复杂了,这一题,结点还不用数字表示,偏偏用字符串表示,所以我还得建立一个映射map,来快速查找字符串对应的节点序号!这一题可以说是昨天 紧急救援 那一题的加难版。

谈一谈map容器:
map<string,int> strMap; //以string为key,以int为value,关键字key在前面
strMap[“PAT”] = 1;
strMap[“PTA”] = 2;
strMap[“DBS”] = 3;
strMap[“ABA”] = 4;
可以直接这样像数组一样,赋值。表示字符串"PAT"与数字1建立了一个映射关系
这样,我们日后在查找字符串对应的数字时,直接int x = strMap[“PTA”]就可以了!

这一题的具体实现过程,我也是参考了这位博主的代码,写得很清楚的:https://blog.csdn.net/ly59782/article/details/79665353#commentBox

他用了迪杰斯特拉算法的优化—优先队列,我就没有用了,毕竟刚学,先把传统写法写会。
这题也让我见识到了,迪杰斯特拉算法保存路径状态的写法,用了大量数组来记录信息,这是一种非常常见的思路,要好好体会!如果是我,可能又会用dfs搜,那就慢了。。。

这道题弄了差不多一个半小时,总算是完成了,写出来之后真的是感觉神清气爽啊哈哈
AC代码:

#include<iostream>
#include<vector>
#include<map>
using namespace std;const int INF = 0x3f3f3f3f;
const int maxn = 200 + 10;
map<string,int> mp;                   //建立映射,便于查找字符串和顶点序号的关系 int n, k, w;                      //w代表权值
struct edge{int to,cost;
};
vector <edge> G[maxn];
int num[maxn];///每个城镇敌军数量int dis[maxn];///最短距离
int cnt[maxn];///解放城镇数量
int sumnum[maxn];///能杀伤多少敌军
int pred[maxn];///记录路,pred[i]表示i的上一个节点序号
int cntshort[maxn];///到某一个顶点的,最短路条数
int book[maxn];
vector <int> ljd;
int s, des;void dijsk()
{//初始化无穷大 for(int i = 0;i < n;i++)dis[i] = INF;//再根据边的情况初始化dis数组 dis[s] = 0;cntshort[s] = 1;                       //这句话暂时不懂?book[s] = 1;//查看起点所有可以出去的边 for(int i = 0;i < G[s].size();i++){int next = G[s][i].to;               //这条边s能到的点 dis[next] = G[s][i].cost;           //记录下它的权值//下面三句之前弄掉了,导致答案不对 cntshort[next] = 1;                 //这里最短路径的条数就变成1sumnum[next] = num[next];           //这里杀伤的敌军数要初始化 pred[next] = s;                     //这里next节点的前一个是s节点 }//现在dis数组已经初始化完毕!开始dijsk核心语句 int min, minindex;for(int i = 1;i <= n - 1;i++)      //n为节点个数 {min = INF;minindex = 0;for(int i = 0;i < n;i++)       //遍历dis数组,找出dis值最小的那个节点 {if(dis[i] < min && book[i] != 1)        //不能是最短路已经确定好的点 {min = dis[i];minindex = i;}} book[minindex] = 1;//对minindex这个点进行出边 for(int i = 0;i < G[minindex].size();i++){edge& e = G[minindex][i];           //这个边挑出来 int d2 = dis[minindex] + e.cost; //待更新的距离 //如果可以松弛,就更新dis值 if(dis[e.to] > d2){dis[e.to] = d2;                 //dis更新pred[e.to] = minindex;          //路径更新cnt[e.to] = cnt[minindex] + 1;  //解放城市数量加 1sumnum[e.to] = sumnum[minindex] + num[e.to];       //杀死军队数更新cntshort[e.to] = cntshort[minindex];  //最短路条数 }else if(dis[e.to] == d2){cntshort[e.to] += cntshort[minindex];     //之和if(cnt[e.to] < cnt[minindex] + 1)       //如果解放城市多{//那么路径要更新,解放城市数要更新,消灭敌军数也更新 pred[e.to] = minindex;cnt[e.to] = cnt[minindex] + 1;sumnum[e.to] = sumnum[minindex] + num[e.to];} else if(cnt[e.to] == cnt[minindex] + 1)   //若解放城市数也相等{//那么看消灭的敌军数if(sumnum[e.to] < sumnum[minindex] + num[e.to]){sumnum[e.to] = sumnum[minindex] + num[e.to];pred[e.to] = minindex;} } }}//更新完之后回到上面,继续寻找下一个minindex即可 }
}void dfs(int *p, int x,vector <int>& a)
{//反着搜,从目标des开始,递归边界就是x == s的时候 if(x == s){a.push_back(x);return ;}dfs(p, p[x], a);           //递归思想:先把我前面的节点装到向量a中去 a.push_back(x);               //再把我装进去
}int main()
{string city[maxn];string city1, city2;cin >> n >> k >> city1 >> city2;     //输入城镇数,道路数,起点城市和终点城市city[0] = city1;                        //city数组存代表城市的字符串mp[city1] = 0;                            //建立一个string 与下标的映射?//输入各城市军队的数量 for(int i = 1;i < n;i++){cin >> city[i] >> w;mp[city[i]] = i;                    //建立映射,便于查找 num[i] = w;                         //存储军队的个数 }//开始城市的序号,目标城市的序号 s = 0;des = mp[city2];                int u, v;//开始输入边,i从0开始 for(int i = 0;i < k;i++){cin >> city1 >> city2 >> w;u = mp[city1];   v = mp[city2];     //把字符串利用map翻译成点的序号 //将边的信息存到邻接表中,与以前的操作一样 G[u].push_back((edge){v, w});      //(edge)强转u对应的to节点是-->v G[v].push_back((edge){u, w});} //输入完成之后,就可以开始Dijsk算法dijsk(); dfs(pred, des, ljd);cout<<city[0];         //首先输出起点 for(int i = 1;i<ljd.size();++i){     //ljd[0] = s;cout<<"->"<<city[ljd[i]];}printf("\n%d %d %d",cntshort[des],dis[des],sumnum[des]);return 0;
}

代码很长,主要是很多数据结构有点复杂,算法思想其实不难,在迪杰斯特拉算法的判断过程中(杀敌数,解放城市数等等)根据题意变一下

天梯赛习题:直捣黄龙(Dijsk算法 + dfs + 路径状态存储)相关推荐

  1. Python入门习题(57)——团体程序设计天梯赛习题:古风排版

    天梯赛习题:古风排版 题目描述 解题思路 数据结构 算法 细节 参考答案 测试用例 小结 题目描述 中国的古人写文字,是从右向左竖向排版的.本题就请你编写程序,把一段文字按古风排版. 输入格式: 输入 ...

  2. L2-001. 紧急救援-PAT团体程序设计天梯赛GPLT(Dijkstra算法)

    作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求 ...

  3. PTA团体程序设计天梯赛篇(四)----几何+算法专题

    几何+算法专题 算法 字符串算法 最长对称子串(Manacher 算法) 动态规划 至多删三个字符 几何 神坛(极角排序) 算法 字符串算法 最长对称子串(Manacher 算法) 题目链接 解题思路 ...

  4. 天梯赛习题:福到了(递归打印)

    L1-054 福到了 (15 分) "福"字倒着贴,寓意"福到".不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出.这里要处理的每个汉字是由一个 N ...

  5. 大专普通本科、搞算法的(蓝桥杯、ACM、天梯赛)-后续成长之路

    2021年1月 1.首先要清楚算法究竟能为程序作出什么样的贡献: 请查阅:<[算法之美]改变世界的十位算法大师> url:https://blog.csdn.net/kexuanxiu11 ...

  6. 算法比赛经历--蓝桥杯,天梯赛,力扣,牛客,cf,acwing,acm

    第一次蓝桥杯,是去年,用c++写,混了个省二等. 今年蓝桥杯,用java写,水进上海前三,混了个省一等,国赛混了个二等 天梯赛混了个团三... 然后是查缺补漏,扩展算法知识点,真枯燥,临近白发,刷题太 ...

  7. 2022年天梯赛比赛真题,L1基础题,C语言,没有算法的那种

    目录 L1-1 今天我要赢 (5 分) L1-2 种钻石 (5 分) L1-3 谁能进图书馆 (10 分) L1-4 拯救外星人 (10 分) L1-5 试试手气 (15 分) L1-6 斯德哥尔摩火 ...

  8. 基础算法题——天梯赛座位分配(化繁为简)

    天梯赛座位分配 天梯赛每年有大量参赛队员,要保证同一所学校的所有队员都不能相邻,分配座位就成为一件比较麻烦的事情.为此我们制定如下策略:假设某赛场有 N 所学校参赛,第 i 所学校有 M[i] 支队伍 ...

  9. 【CCCC】PAT : 团体程序设计天梯赛-练习集 L3 答案(01-23)

    [CCCC]PAT : 团体程序设计天梯赛-练习集 L3 答案 顶着满课,整整一星期,终于咕完了.(:´д`)ゞ 知识点分类(23): 1.搜索模拟(5):BFS,DFS,最短路,路径打印 2.计算几 ...

最新文章

  1. 生态伙伴 | 番茄君入驻飞书,帮你一招搞定时间管理,告别拖延症!
  2. R语言层次聚类:通过内平方和(Within Sum of Squares, WSS)选择最优的聚类K值、以内平方和(WSS)和K的关系并通过弯头法(elbow method)获得最优的聚类个数
  3. 为什么神经网络会把乌龟识别成步枪?现在的 AI 值得信任吗?
  4. 天津科技大学计算机科学与信息工程学院,天津科技大学人工智能学院欢迎您!...
  5. easyui dialog 中嵌入html页面
  6. XGBoost的参数说明
  7. java基础-关键字final
  8. 小程序复制内容至剪贴板
  9. 基于JAVA+SpringMVC+Mybatis+MYSQL的高考志愿填报管理系统
  10. matlab和本机MySQL链接
  11. activemq部署
  12. GBase数据库监控
  13. 前所未知的Bug(IDEA 和 金山词霸2016的冲突)
  14. 用Form 表单认证实现单点登录(Single Sign On) 作者:寒羽枫(cityhunter172)
  15. 如何做好性能压测(一) | 压测环境的设计和搭建
  16. 【SDX12】高通SDX12 NatType功能分析及实现
  17. Java——nefu
  18. matlab双曲函数
  19. Mybatis中column用法
  20. python字符串加双引号是什么意思_python字符串表示什么?

热门文章

  1. 在本地计算机无法启动t6,T6服务无法启动,有以下提示,请问如何解决,谢谢!...
  2. C语言,指针指针指针
  3. 2022-2028年全球与中国零售会计软件行业发展趋势及竞争策略研究
  4. Windows CE下的网络监测工具(上)
  5. NTFS、FAT32、exFAT这三种格式的区别
  6. DynamicViT论文概要
  7. 学习React第三篇:在React组件上设置属性(PropTypes)
  8. python解决数据框中添加一行或者一列(DataFrame的行列处理)
  9. 航海王启航服务器维修,新手疑难杂症解决航海王启航不走冤枉路
  10. 配置AAA认证和授权