Dijkstra专题

Public Bike Management (30)

Link

卡了半天原来是看漏了这句话: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)

Link

和上一题属于同一类题型,都是用 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;
}
posted @ 2022-06-22 14:12  Ryomk  阅读(16)  评论(0编辑  收藏  举报