hdu 4284 状态压缩dp

题意: 有N 个点的无向图,要去其中 h个地点做事,做事需要先办理护照,之后可以挣一定数量的钱,知道了一开始有的总钱数,和 一些城市之间

          道路的花费,问可不可以在 指定的 h 个城市打完工,并回到起点 1.

链接:点我

是个好题!!!

状态转移方程dp[s][i]=max(dp[s][i],dp[s'][j]-maps[j][i]-d[i]+c[i]);

dp[s][i]表示当在状态s的时候最后再i城市打工的最多剩余钱数。

2
4 5 10  //4个点,5个道路,10单位的钱
1 2 1
2 3 2
1 3 2
1 4 1
3 4 2
3    //3个必去的
1 8 5  //编号,消耗,赚的
2 5 2
3 10 1
2 1 100
1 2 10000
1
2 100000 1

YES
NO
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define INF 99999999
 7 typedef long long LL;
 8 using namespace std;
 9 
10 const int MAX=(1<<16)+10;
11 int n,m,val,h;
12 int s[20],c[20],d[20];
13 int dp[MAX][20],dist[110][110];
14 
15 void Init(int num){
16     for(int i=0;i<=num;++i){
17         for(int j=i+1;j<=num;++j)dist[i][j]=dist[j][i]=INF;
18     }
19 }
20 
21 void floyd(){
22     for(int k=1;k<=n;++k){
23         for(int i=1;i<=n;++i){
24             for(int j=1;j<=n;++j){
25                 dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
26             }
27         }
28     }
29 }
30 
31 void DP(){
32     int bit=1<<(h+1);
33     memset(dp,-1,sizeof dp);
34     dp[1][0]=val;
35     for(int i=1;i<bit;++i){
36         for(int j=0;j<=h;++j){
37             if(dp[i][j] == -1)continue;
38             for(int k=1;k<=h;++k){
39                 if(dp[i][j]<dist[s[j]][s[k]]+d[k])continue;
40                 int p=1<<k,w=c[k]-d[k];     //可以去
41                 if(i&p)continue;        //已经去过
42                 dp[i|p][k]=max(dp[i|p][k],dp[i][j]-dist[s[j]][s[k]]+w);
43             }
44         }
45     }
46     bool flag=false;
47     for(int i=0;i<=h;++i)if(dp[bit-1][i]-dist[s[i]][1]>=0)flag=true;    //没返回过1
48     if(flag)printf("YES
");
49     else printf("NO
");
50 }
51 
52 int main(){
53     int t,u,v,w;
54     scanf("%d",&t);
55     while(t--){
56         scanf("%d%d%d",&n,&m,&val);
57         Init(n);
58         for(int i=0;i<m;++i){
59             scanf("%d%d%d",&u,&v,&w);
60             dist[u][v]=dist[v][u]=min(dist[u][v],w);
61         }
62         scanf("%d",&h);
63         for(int i=1;i<=h;++i){
64             scanf("%d%d%d",&s[i],&c[i],&d[i]);
65         }
66         floyd();
67         s[0]=1,c[0]=d[0]=0;
68         DP();
69     }
70     return 0;
71 }
原文地址:https://www.cnblogs.com/cnblogs321114287/p/4347814.html