Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 1585 | Accepted: 428 |
Description

Input
x=y=len=kind=0 means end of the path explanation.
N=M=K=0 means end of the input.
Output
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);
}
}