博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
uva 10537 Toll! Revisited(优先队列优化dijstra及变形)
阅读量:4945 次
发布时间:2019-06-11

本文共 2733 字,大约阅读时间需要 9 分钟。

大致题意:有两种节点,一种是大写字母,一种是小写字母。

首先输入m条边。当经过小写字母时须要付一单位的过路费。当经过大写字母时,要付当前財务的1/20做过路费。

问在起点最少须要带多少物品使到达终点时还有k个物品。

当有多条符合条件的路径时输出字典序最小的一个。

思路:已知终点的权值,那么能够从终点向前推。

求终点到起点的最短路径,然后按字典序打印路径。

比較难处理的是:向前推时前驱节点的权值计算。列个方程算算就能够了,主要时不能整除的情况。

计算前驱结点dis值的时候,同一时候记录(i,j)的边权值。这是打印路径的根据。

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long#define _LL __int64using namespace std;const int INF = 0x3f3f3f3f;const int maxm = 1010;const int maxn = 60;struct node{ int v,w; int next;}edge[maxm];int m;int pre[maxn],cnt;int start,end;LL dis[maxn],p;int vis[maxn];vector
ans;void init(){ cnt = 0; memset(pre,-1,sizeof(pre)); for(int i = 0; i < maxm; i++) edge[i].w = 0;}void add(int u, int v){ edge[cnt].v = v; edge[cnt].next = pre[u]; pre[u] = cnt++;}void dijstra(){ priority_queue
, vector
>, greater
> > que; while(!que.empty()) que.pop(); memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[end] = p; que.push(make_pair(dis[end],end)); while(!que.empty()) { int u = que.top().second; que.pop(); if(vis[u]) continue; vis[u] = 1; for(int i = pre[u]; i != -1; i = edge[i].next) //松弛相邻节点 { if(vis[edge[i].v]) continue; int v = edge[i].v; if(u < 26) { //计算前驱结点的权值,推断是否整除,若不整除,尝试加1继续推断 if(dis[u]%19 == 0) { if(dis[v] > dis[u]/19*20) { dis[v] = dis[u]/19*20; edge[i].w = edge[i^1].w = dis[v]-dis[u]; que.push(make_pair(dis[v],v)); } } else if( (dis[u]+1)%19 ) { if(dis[v] > (dis[u]+1)*20/19) { dis[v] = (dis[u]+1)*20/19; edge[i].w = edge[i^1].w = dis[v]-dis[u]; que.push(make_pair(dis[v],v)); } } else { if(dis[v] > (dis[u]+1)*20/19-1 ) { dis[v] = (dis[u]+1)*20/19-1; edge[i].w = edge[i^1].w = dis[v]-dis[u]; que.push(make_pair(dis[v],v)); } } } else { if(dis[v] > dis[u]+1) { dis[v] = dis[u]+1; edge[i].w = edge[i^1].w = 1; que.push(make_pair(dis[v],v)); } } } }}void solve(){ ans.clear(); int now; now = start; ans.push_back(now); while(now != end) { int tmp = 1<<6; for(int i = pre[now]; i != -1; i = edge[i].next) { int v = edge[i].v; //由于输出字典序最小的,所以求出满足dis[now] - dis[v] == edge[i].w中最小的v if(dis[now] - dis[v] == edge[i].w && v < tmp) { tmp = v; } } ans.push_back(tmp); now = tmp; } printf("%c",ans[0]+'A'); for(int i = 1; i < (int)ans.size(); i++) printf("-%c",ans[i]+'A'); printf("\n");}int main(){ int item = 1; char t1,t2; while(~scanf("%d",&m)) { if(m == -1) break; init(); getchar(); for(int i = 0; i < m; i++) { scanf("%c %c",&t1,&t2); getchar(); add(t1-'A',t2-'A'); add(t2-'A',t1-'A'); } scanf("%lld %c %c",&p,&t1,&t2); start = t1-'A'; end = t2-'A'; dijstra(); printf("Case %d:\n",item++); printf("%lld\n",dis[start]); solve(); } return 0;}

转载于:https://www.cnblogs.com/llguanli/p/6736035.html

你可能感兴趣的文章
Breaking parallel loops in .NET C# using the Stop method z
查看>>
[轉]redis;mongodb;memcache三者的性能比較
查看>>
让你的WPF程序在Win7下呈现Win8风格主题
查看>>
构建Docker Compose服务堆栈
查看>>
浮点数内存如何存储的
查看>>
JsonCpp 的使用
查看>>
问题账户需求分析
查看>>
hp 服务器通过串口重定向功能的使用
查看>>
此博客不再发表对自己私事的看法
查看>>
导致Asp.Net站点重启的10个原因
查看>>
【PMP】Head First PMP 学习笔记 第一章 引言
查看>>
抓住云机遇编排工作 搞定复杂IT工作流
查看>>
MYSQL的longtext字段能放多少数据?
查看>>
MTK 平台上如何给 camera 添加一种 preview size
查看>>
云计算最大难处
查看>>
mysql定时备份自动上传
查看>>
17岁时少年决定把海洋洗干净,现在21岁的他做到了
查看>>
《写给大忙人看的java se 8》笔记
查看>>
倒计时:计算时间差
查看>>
Linux/windows P2V VMWare ESXi
查看>>