(中等) 状态压缩dp HOJ 2480 The best travel design

The best travel design

My Tags  (Edit)
Source : ACM South Central China
Time limit : 3 secMemory limit : 64 M

Submitted : 104, Accepted : 21

Description

(中等) 状态压缩dp  HOJ  2480 The best travel design - 恶魔仁 - 恶魔仁

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 arrived. The third line is N integers, the ith 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 explaination. 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


题意:给出一个图,节点数最多15个,给出旅游的天数K,每个地点参观的时间和必须参观的地点,求出在K天内从1出发最后回到1,最多能参观多少个景点。我觉得这里可以经过一个景点但是不参观。。。。参观过的景点也可以经过,也是不参观。 

思路:根据我的理解,首先求出每两点之间的最少要用多少时间,然后我们用dp[s][j]表示状态为s,目前在j景点花费的时间最少。那么转移方程是dp[to][k] = dp[s][j] + time[j][k] + stay[k]; 最后看一下最少的时间是否能在K*12以内,能就是能到达这个状态,否则不能。

代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
using namespace std;
#define max(a,b) (a) < (b) ? (b) : (a)
#define LL long long
#define eps 1e-8
const int maxn = (1<<15)+10;
const int inf = 1e9;
double dp[maxn][20];
int p[20];
double cost[20][20];
int stay[20];

int must_vis , N , M , K ;

void init()
{
must_vis = 0;
for (int i = 1 ; i <= N ; ++i)
for (int j = 1 ; j <= N ; ++j)
cost[i][j] = inf;
memset(dp,0,sizeof(dp));
}

void input()
{
int a;
for (int i = 0 ; i < M ; ++i) 
{
scanf("%d",&a);
must_vis += p[a];
}
for (int i = 1 ; i <= N ; ++i) scanf("%d",stay+i);
double dis;
int x , y , d , sel;
while (scanf("%d%d%d%d",&x,&y,&d,&sel))
{
if (x+y+d+sel==0) break;
if (sel==0)
dis = d/80.0;
else 
dis = d/120.0;
cost[x][y] = min(cost[x][y],dis);
cost[y][x] = cost[x][y];
}
for (int k = 1 ; k <= N ; ++k)
for (int i = 1 ; i <= N ; ++i) if (cost[i][k]!=inf)
for (int j = 1 ; j <= N ; ++j) if (cost[k][j]!=inf)
cost[i][j] = min(cost[i][j],cost[i][k]+cost[k][j]);
for (int i = 1 ; i <= N ; ++i)
cost[i][i] = 0;
}

void solve()
{
int max_s = 1<<N;
for (int s = 0 ; s < max_s ; ++s)
for (int j = 1 ; j <= N ; ++j) dp[s][j] = inf;

dp[0][1] = 0;
for (int s = 0 ; s < max_s ; ++s)
{
for (int j = 1 ; j <= N ; ++j) if (dp[s][j]!=inf)
{
for (int k = 1 ; k <= N ; ++k) if (!(p[k]&s))
{
int to = s + p[k];
if (dp[to][k] > dp[s][j] + cost[j][k] + stay[k])
dp[to][k] = dp[s][j] + cost[j][k] + stay[k];
}
}
}
bool ok = false;
int ans = 0;
for (int s = 0 ; s < max_s ; ++s) if ((s&must_vis)==must_vis)
{
for (int j = 1 ; j <= N ; ++j) if (dp[s][j]!=inf && dp[s][j] + cost[j][1] < K*12+eps)
{
int cnt = 0;
for (int k = 1 ; k <= N ; ++k) if (s&p[k])
++cnt;
if (cnt > ans) ans = cnt;
}
}
if (ans==0) printf("No Solution\n");
else printf("%d\n",ans);

}


int main()
{
p[1] = 1;
for (int i = 2 ; i <= 15 ; ++i) p[i] = p[i-1]<<1;
while (scanf("%d%d%d",&N,&M,&K)==3)
{
if (N+M+K==0) return 0;
init();
input();
solve();
}
}

题后语:旅游也要这样斤斤计较的话不就太没意思了吗?虽然通过这种方式,能从实际上增加了自己能参观的地方,但是旅游的目的不就是将自己从那个纷繁的社会中暂时的走出来,让自己享受一下没有勾心斗角,没有功利之心的世界。所以旅游最重要的是开心,不要干什么事都利益最大化,这样活着实在是太累了。。。利益最大不一定就能开心,利益少了很多也不一定就会很苦恼,最重要是有一颗简单的心灵,开阔的心胸。。。我自己就喜欢简单的生活,没有算计,没有投机取巧的生活。。。主要是自己太笨。。。呵呵,是不是很天真。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值