PAT 1018的陷阱

这道题目要把所有最短路径先找到并且保存好,然后再遍历找最优的。如果一边找最短路径一遍贪心,可能会导致整体表现比较好的路线在前面被扔掉。

第二要注意题目的理解,从PBMC出发,到终点,路上把每个站点都调整到最优。路上如果后面有站点可以获得到多余的车,也不能把车带回来给前面的站点。从PBMC带出来的车一定要保证每时每刻都够用。

针对这些坑设计了一些测试数据,把数据和我AC的程序都贴出来。

#include<stdio.h>
#include<vector>
#include<algorithm>
#include<set>

#define MY_INT_MAX 1000000000

using namespace std;

#undef DEBUG
int n,cmax,sp,m;
int map[501][501];
int bike[501];
bool inS[501];
vector<vector<int>> all_paths[501];
int length[501];

int main()
{
	//freopen("input.in","r",stdin);
	//freopen("output.out","w",stdout);

	//input
	scanf("%d%d%d%d",&cmax,&n,&sp,&m);
	int i,j,from,to,time;
	for(i=1;i<=n;i++)
		scanf("%d",&bike[i]);
	for(i=0;i<=n;i++)
		for(j=0;j<=n;j++)
			map[i][j]=MY_INT_MAX;
	for(i=0;i<m;i++)
	{
		scanf("%d%d%d",&from,&to,&time);
		map[from][to]=time;
		map[to][from]=time;
	}

	//shortest path
	for(i=1;i<=n;i++)
	{
		inS[i]=false;
		length[i]=map[0][i];
		if(length[i]<MY_INT_MAX)
		{
			vector<int> v;
			v.push_back(i);
			vector<vector<int>> vv;
			vv.push_back(v);
			all_paths[i]=vv;
		}
	}
	inS[0]=true;

	int min;
	int minV;
	while(!inS[sp])
	{
		minV=MY_INT_MAX;
		for(i=1;i<=n;i++)
		{
			if(!inS[i] && length[i]<minV)
			{
				min=i;
				minV=length[i];
			}
		}

#ifdef DEBUG
	int debug_i;
	for(debug_i=1;debug_i<=n;debug_i++)
	{
		printf("length[%d]=%d ",debug_i,length[debug_i]);
	}
	printf("\nin this iteration, min=%d, length[min]=%d\n",min,length[min]);
#endif
		inS[min]=true;
		for(i=1;i<=n;i++)
		{
			if(inS[i])
				continue;
#ifdef DEBUG
	printf("now i=%d, length[i]=%d\n",i,length[i]);
#endif
			if(length[i]>map[min][i]+length[min])
			{
#ifdef DEBUG
	printf("find a new short path to %d\n",i);
#endif
				length[i]=map[min][i]+length[min];
				all_paths[i].clear();
				for(vector<vector<int>>::iterator it=all_paths[min].begin();it!=all_paths[min].end();it++)
				{
					vector<int> nv= *it;
					nv.push_back(i);
					all_paths[i].push_back(nv);
				}
			}
			else if(length[i]==map[min][i]+length[min])
			{
#ifdef DEBUG
	printf("find an equal path to %d\n",i);
#endif
				for(vector<vector<int>>::iterator it=all_paths[min].begin();it!=all_paths[min].end();it++)
				{
					vector<int> nv= *it;
					nv.push_back(i);
					all_paths[i].push_back(nv);
				}
			}
		}
	}

	int minSend=99999999;
	int send;
	int record_send;
	vector<vector<int>> possible_paths;

	//find the paths with less send
	for(vector<vector<int>>::iterator it=all_paths[sp].begin();it!=all_paths[min].end();it++)
	{
		send=0;
		record_send=0;
		for(vector<int>::iterator jt=it->begin();jt!=it->end();jt++)
		{
			send+=cmax/2-bike[*jt];
			if(send>record_send)
				record_send=send;
		}
#ifdef DEBUG
	printf("record_send=%d, minSend=%d\n",record_send,minSend);
#endif
		if(record_send<minSend)
		{
			minSend=record_send;
			possible_paths.clear();
			possible_paths.push_back(*it);
		}
		else if(record_send == minSend)
		{
			possible_paths.push_back(*it);
		}
	}

	int store;
	int minStore=99999999;
	vector<vector<int>>::iterator bestPath;
	for(vector<vector<int>>::iterator it=possible_paths.begin();it!=possible_paths.end();it++)
	{
		store=minSend;
		for(vector<int>::iterator jt=it->begin();jt!=it->end();jt++)
		{
			store=store-(cmax/2-bike[*jt]);
		}
#ifdef DEBUG
	printf("this path, store=%d\n",store);
#endif
		if(store<minStore)
		{
			minStore=store;
			bestPath=it;
		}
	}
	printf("%d 0",minSend);
	for(vector<int>::iterator jt=bestPath->begin();jt!=bestPath->end();jt++)
		printf("->%d",*jt);
	printf(" %d",minStore);
	
	return 0;
}
测试数据:

10 9 3 12
1 1 1 1 1 9 9 8 9
0 1 1
1 2 1
2 3 1
0 4 2
4 5 1
5 3 1
0 6 1
6 7 1
7 3 1
0 8 1
8 9 1
9 3 1

16 4 4 6
16 2 1 0
0 1 2
1 4 2
0 2 1
2 4 1
0 3 1
3 4 1

10 7 6 8
0 0 10 10 10 0 9
0 1 1
1 2 1
2 3 1
3 4 1
4 5 1
5 6 1
0 7 5
7 6 1


10 5 5 6
10 10 9 9 10
0 1 1
1 2 1
2 5 1
0 3 1
3 4 1
4 5 1


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值