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\n");

49     else printf("NO\n");

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 }

 

你可能感兴趣的:(HDU)