Dijkstra专题
Public Bike Management (30)
卡了半天原来是看漏了这句话:If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.
最后输出描述中也有一句:Note that if such a path is not unique, output the one that requires minimum number of bikes that we must take back to PBMC.
因此是要先满足sendTo
最小,其次才是takeBack
。
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> using namespace std; const int N=510; const int PBMC=0; const int INF=0x3f3f3f3f; int cmax,n,sp,m; int c[N],g[N][N],dis[N]; bool vis[N]; vector<int>pre[N]; vector<int>tmpPath,bestPath(N); int bestTake=INF,bestSend=INF; void Dijkstra(){ memset(dis,63,sizeof(dis)); memset(vis,false,sizeof(vis)); dis[0]=0; for(int i=1;i<=n;++i){ int u=-1,minv=INF; for(int j=0;j<=n;++j) if(!vis[j]&&dis[j]<minv){ u=j; minv=dis[j]; } if(u==-1) break; vis[u]=true; for(int i=1;i<=n;++i) if(!vis[i]&&g[u][i]<INF){ if(dis[i]>dis[u]+g[u][i]){ dis[i]=dis[u]+g[u][i]; pre[i].clear(); pre[i].push_back(u); }else if(dis[i]==dis[u]+g[u][i]) pre[i].push_back(u); } } } void DFS(int v){ tmpPath.push_back(v); if(v==PBMC){ int sendTo=0,takeBack=0; //注意tmpPath[tmpPath.size()-1]==PBMC,默认是0,如果从这里开始就会让send变大 for(int i=tmpPath.size()-2;i>=0;--i){ if(c[tmpPath[i]]<cmax){ int tmpSend=cmax-c[tmpPath[i]]; if(tmpSend<=takeBack) { takeBack-=tmpSend; continue; }else tmpSend-=takeBack,takeBack=0; sendTo+=tmpSend; } else takeBack+=c[tmpPath[i]]-cmax; } if(sendTo<bestSend){ bestSend=sendTo; bestTake=takeBack; bestPath=tmpPath; }else if(sendTo==bestSend&&takeBack<bestTake){ bestTake=takeBack; bestPath=tmpPath; } }else{ for(int i=0;i<pre[v].size();++i) DFS(pre[v][i]); } tmpPath.pop_back(); } int main() { scanf("%d%d%d%d",&cmax,&n,&sp,&m); cmax>>=1; memset(g,INF,sizeof(g)); for(int i=1;i<=n;++i) scanf("%d",&c[i]); for(int i=1;i<=m;++i){ int s1,s2,t; scanf("%d%d%d",&s1,&s2,&t); g[s1][s2]=g[s2][s1]=t; } Dijkstra(); DFS(sp); printf("%d ",bestSend); for(int i=bestPath.size()-1;i>=1;--i) printf("%d->",bestPath[i]); printf("%d ",bestPath[0]); printf("%d\n",bestTake); return 0; }
All Roads Lead to Rome (30)
和上一题属于同一类题型,都是用 Dijkstra 算法求最短路径,而且需要通过记录前驱节点来遍历所有最短路径。
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> using namespace std; const int N=210; const int MAXN=26*26*26; const int INF=0x3f3f3f3f; int n,k; int startCity,endCity; int mapIndex[MAXN],revMapIndex[N]; int happy[N],g[N][N],dis[N]; bool vis[N]; vector<int>pre[N]; vector<int>tmpPath,bestPath(N); int bestHappy,bestCount=INF,bestRoutes; inline int toNumber(char *name){ return (name[0]-'A')*26*26+(name[1]-'A')*26+(name[2]-'A'); } inline void toCString(int num){ num=revMapIndex[num]; char name[4]; name[2]=(num%26)+'A'; num/=26; name[1]=(num%26)+'A'; num/=26; name[0]=(num%26)+'A'; printf("%c%c%c",name[0],name[1],name[2]); } void Dijkstra(){ memset(dis,63,sizeof(dis)); memset(vis,false,sizeof(vis)); dis[startCity]=0; for(int i=1;i<=n;++i){ int u=-1,minv=INF; for(int j=1;j<=n;++j) if(!vis[j]&&dis[j]<minv){ u=j; minv=dis[j]; } if(u==-1) break; vis[u]=true; for(int j=1;j<=n;++j) if(!vis[j]&&g[u][j]<INF){ if(dis[j]>dis[u]+g[u][j]){ dis[j]=dis[u]+g[u][j]; pre[j].clear(); pre[j].push_back(u); }else if(dis[j]==dis[u]+g[u][j]) pre[j].push_back(u); } } } void DFS(int v){ tmpPath.push_back(v); if(v==startCity){ bestRoutes++; int cur=0; for(int i=tmpPath.size()-2;i>=0;--i){ cur+=happy[tmpPath[i]]; } if(cur>bestHappy){ bestHappy=cur; bestCount=tmpPath.size(); bestPath=tmpPath; }else if(cur==bestHappy&&tmpPath.size()<bestCount){ bestCount=tmpPath.size(); bestPath=tmpPath; } }else{ for(int i=0;i<pre[v].size();++i) DFS(pre[v][i]); } tmpPath.pop_back(); } int main() { char name1[5],name2[5]="ROM"; scanf("%d%d%s",&n,&k,name1); startCity=toNumber(name1); endCity=toNumber(name2); mapIndex[startCity]=1; revMapIndex[1]=startCity; memset(g,INF,sizeof(g)); for(int i=2;i<=n;++i){ scanf("%s",name1); int s=toNumber(name1); mapIndex[s]=i; revMapIndex[i]=s; scanf("%d",&happy[i]); } startCity=mapIndex[startCity]; endCity=mapIndex[endCity]; for(int i=1;i<=k;++i){ scanf("%s %s",name1,name2); int s1=mapIndex[toNumber(name1)],s2=mapIndex[toNumber(name2)]; scanf("%d",&g[s1][s2]); g[s2][s1]=g[s1][s2]; } Dijkstra(); DFS(endCity); printf("%d %d %d %d\n",bestRoutes,dis[endCity],bestHappy,bestHappy/(bestCount-1)); for(int i=bestPath.size()-1;i>=1;--i){ toCString(bestPath[i]); printf("->"); } toCString(bestPath[0]); printf("\n"); return 0; }
本文作者:Ryomk
本文链接:https://www.cnblogs.com/preccrep/p/16393758.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步