The Best Travel Design
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 1585 | Accepted: 428 |
Description
![](https://i-blog.csdnimg.cn/blog_migrate/9960c1fd93e160b61af88ae65bf1e02c.jpeg)
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.
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);
}
}