1018 Public Bike Management (30分) (迪杰斯特拉+dfs)

思路就是dijkstra找出最短路,dfs比较每一个最短路。
dijkstra可以找出每个点的前一个点, 所以dfs搜索比较的时候怎么处理携带和带走的数量就是关键,考虑到这个携带和带走和路径顺序有关,所以可以用下面的写法,看代码就可以了。
最开始的时候是想用一个偏动态规划的写法做,但是因为题目的显示,既要带去的车数量最少,又要求从一个点带走的车数量最少,所以如果过动规的话,对于一个点的多个最短路,就会选择带去数量最少,带走车数最少的路径,但是如果这个点后面的点的车辆数少一标准量的一半的话,前面带的是最少的,这样相当于携带的车的数量就多了,这样就矛盾了。
当时挺纠结的,因为只写过一道类型的题,还是用动规的写法写的,那个权值只有两个,也是pat的题,这个主要是权值矛盾了, 所以不能用动规的思想写。

#include <bits/stdc++.h>
using namespace std;
const int maxn=505;
const int INF=0x3f3f3f3f;

int g[maxn][maxn];
vector<int> pre[maxn];
int C,N,M,SP;
int vis[maxn],num[maxn],d[maxn];

void dijkstra()
{
	d[0]=0;

	for (int i=0;i<N;i++) {
		int u=-1,tmp=INF;
		for (int j=0;j<=N;j++) {
			if (!vis[j]&&d[j]<tmp) {
				tmp=d[j];
				u=j;
			}
		}
		if (u==-1) break;
		vis[u]=1;
		for (int j=0;j<=N;j++) {
			if (j==u) {
				continue;
			}
			if (d[u]+g[u][j]<d[j]) {
				d[j]=d[u]+g[u][j];
				pre[j].clear();
				pre[j].push_back(u);
			}
			else if (d[u]+g[u][j]==d[j]) {
				pre[j].push_back(u);
			}
		}
	}
}

int path[maxn],acnt=0;
int ansn=INF,anst=INF,ansp[maxn];
void dfs(int u,int need,int take,int cnt)
{
	path[cnt]=u;
	if (u==0) {
		// for (int i=0;i<cnt;i++) {
		// 	printf("%d ",path[i]);
		// }
		// puts("");
		// printf("need %d take %d
",need,take);
		if (need<ansn) {
			ansn=need;
			anst=take;
			acnt=cnt;
			for (int i=0;i<cnt;i++) {
				ansp[i]=path[i];
			}
			
		}
		else if (need==ansn) {
			if (take<anst) {
				anst=take;
				acnt=cnt;
				for (int i=0;i<cnt;i++) {
					ansp[i]=path[i];
				}
			}
		}
		return ;
	}
	if (num[u]==C/2) {}
	else if (num[u]>C/2) {
		if (need>0) {
			if (num[u]-C/2>=need) {
				take+=num[u]-C/2-need;
				need=0;
			}
			else need-=num[u]-C/2;
		}
		else take+=num[u]-C/2;
	}
	else need+=C/2-num[u];

	int sz=pre[u].size();
	for (int i=0;i<sz;i++) {

		dfs(pre[u][i],need,take,cnt+1);
	}
}

int main()
{
	// freopen("in.txt","r",stdin);
	scanf("%d%d%d%d",&C,&N,&SP,&M);
	for (int i=1;i<=N;i++) {
		scanf("%d",&num[i]);
	}
	
	memset(g,INF,sizeof(g));
	for (int i=0;i<=N;i++) {
		g[i][i]=0;
		d[i]=INF;
	}

	int u,v,c;
	for (int i=0;i<M;i++) {
		scanf("%d%d%d",&u,&v,&c);
		g[u][v]=c;
		g[v][u]=c;
	}
	dijkstra();
	// for (int i=1;i<=N;i++) {
	// 	printf("%d ",d[i]);
	// }
	// puts("");
	// for (int i=1;i<=N;i++) {
	// 	printf("%d:
",i);
	// 	for (int j=0;j<pre[i].size();j++) {
	// 		printf("%d ",pre[i][j]);
	// 	}
	// 	printf("
");
	// }
	dfs(SP,0,0,0);
	printf("%d %d",ansn,0);
	for (int i=acnt-1;i>=0;i--) {
		printf("->%d",ansp[i]);
	}
	printf(" %d
",anst);
	return 0;
}
原文地址:https://www.cnblogs.com/xyqxyq/p/12328852.html