POJ 3229 The Best Travel Design

The Best Travel Design
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 1585 Accepted: 428

Description

Dou Nai is an excellent ACM programmer, and he felt so tired recently that he wants to release himself from the hard work. He plans a travel to Xin Jiang .With the influence of literature, he wishes to visit Tian Chi, Da Ban Town, Lou Lan mysterious town , Yi Li , and other sights that also have great attraction to him. But the summer vocation time is not long. He must come back before the end of the summer vocation. For visiting more sights and all the necessary sights, he should make a thorough plan. Unfortunately, he is too tired to move, so you must help him to make this plan. Here are some prerequisites: there are two ways of transportation, bus and train, and velocity of the bus is 120km/h and the train is 80km/h. Suppose the travel is started from Urumuqi (point 1), and the end of the travel route is Urumuqi too. You need to spend some time to visit the sights, but the time of each visit is not always equal. Suppose we spend 12 hours on traveling every day.

Input

There are several test cases. For each case, the first line is three integers N, M and K. N (1<=n<=15) is the number of sights, M(0<=M<=N) is total sights he must arrived (sight 1 is always must be arrived) and K is total traveling time (per day). The second line is M integers which sights he must visited. The third line is N integers, the i th integer means the time he will stay in the sight i (per hour). Then several lines follow. Each line is four integers x, y, len and kind, 1<=x, y<=n, 0<len<=1000, means there is a bidirectional path between sights x and y, the distance is len, kind=0 means x and y are connected by train, kind=1 is by bus.
x=y=len=kind=0 means end of the path explanation.
N=M=K=0 means end of the input.

Output

For each case, output maximum sights he will travel with all necessary sights visited or "No Solution" if he can't travel all the sights he like best in time.

Sample Input

3 3 3
1 2 3
10 8 6
1 2 120 0
1 3 60 1
2 3 50 1
0 0 0 0
3 3 2
1 2 3
10 8 6
1 2 120 0
1 3 60 1
2 3 50 1
0 0 0 0
0 0 0

Sample Output

3
No Solution

Source

South Central China 2007 hosted by NUDT


翻译:

Dou Nai是一个优秀的ACM程序员,最近他计划去新疆旅行,他要在暑假结束之前回来,因此他为了看到最多的景色,希望你帮他拟定一个计划

有两种方法实现在两地之间的旅行:公交车或者火车,公交车速度为120km/h,火车速度为80km/h,假设起点与终点都是1号点,每到达一个景点都要在这个景点停留一定时间(这个时间不一定相等),假设我们每天花12个小时旅行

Dou Nai有几个景点是一定要去的

Dou Nai希望你能帮他求出他能到达最多的景点个数,如果他没有办法走完所有他一定要去的景点,就输出No Solution

这道题看起来十分复杂,需要旅行完必须去的景点,还要考虑交通方式的选择

我们首先把这道题当成图论来看,求出每两个景点之间的最短路径

这里有一个贪心原则,我们走到一个景点后在以后中就尽量避开这个点,因为到达这个点不仅要消耗时间,而且还无法使ans++

然后观察数据范围就可以发现这题可以状压,把每个景点是否去过看成状态的一部分

f[s][i]表示状态为s且现在在i点的最小代价,用类似floyd的方法求出f数组。最后判断在k*12以内能够实现的最多景点数量

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
const int maxn=15,inf=1e9;
inline void _read(int &x){
    char t=getchar();bool sign=true;
    while(t<'0'||t>'9')
    {if(t=='-')sign=false;t=getchar();}
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
    if(!sign)x=-x;
}
double f[(1<<maxn)+10][20],cost[20][20];
int stay[20],n,m,K,s,target;
void clear(){
	for(int s0=0;s0<=s;s0++)
	    for(int i=1;i<=n;i++)
	        f[s0][i]=inf;
	f[0][1]=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		    cost[i][j]= i==j?0:inf;
	memset(stay,0,sizeof(stay));
	target=0;
}
int main(){
	while(scanf("%d%d%d",&n,&m,&K)&&(n||m||K)){
		s=(1<<n)-1;
		clear();
		int i,j,x,y,len,kind,k,s0;
		for(i=1;i<=m;i++){
			scanf("%d",&x);
			target|=1<<(x-1);
		}
		for(i=1;i<=n;i++)scanf("%d",&stay[i]);
		while(scanf("%d%d%d%d",&x,&y,&len,&kind)){
			if(!x&&!y&&!len&&!kind)break;
			double time;
			time= kind?len/120.0:len/80.0;
			cost[x][y]=min(cost[x][y],time);
			cost[y][x]=cost[x][y];
		}
		for(k=1;k<=n;k++)
		    for(i=1;i<=n;i++)
		       for(j=1;j<=n;j++)
		           cost[i][j]=min(cost[i][j],cost[i][k]+cost[k][j]);//Floyd求最短路径
		for(s0=0;s0<=s;s0++)
		    for(i=1;i<=n;i++)
		        if(f[s0][i]!=inf)
		            for(j=1;j<=n;j++)
		                if(!(s0&(1<<(j-1))))
		                    f[s0|(1<<(j-1))][j]=min(f[s0|(1<<(j-1))][j],f[s0][i]+cost[i][j]+stay[j]);
		int ans=0;
		for(s0=0;s0<=s;s0++)
		    if((s0&target)==target){
		    	bool flag=0;
		    	for(i=1;i<=n;i++)//讨论s0状态能否到达
		    	    if(f[s0][i]!=inf&&f[s0][i]+cost[i][1]<=K*12)flag=1;
		    	if(!flag)continue;
		    	int cnt=0;
		    	for(i=1;i<=n;i++)
		    	    if(s0&(1<<(i-1)))cnt++;
		    	ans=max(ans,cnt);
			}
		if(ans==0)puts("No Solution");
		else printf("%d\n",ans);
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值