hdu 4114(状压dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4114

思路:首先是floyd预处理出任意两点之间的最短距离。dp[state1][state2][u]表示在该状态state1(已经访问过的景点)、state2(手中有的景点的票)、目前所在的位置时所花费的时间的最小值,于是答案就是dp[(1<<k)-1][state][1]了(0<=state<(1<<n))。

hdu 4114(状压dp)
 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<queue>

 6 #include<vector>

 7 using namespace std;

 8 #define inf 1<<30

 9 #define FILL(a,b) memset(a,b,sizeof(a))

10 

11 int dp[1<<9][1<<9][55];//访问过的+收集的票+当前顶点

12 int pos[55],time[9],f_time[9],map[55][55];

13 int Mask[55];

14 int n,m,k,ans;

15 

16 void floyd()

17 {

18     for(int k=1; k<=n; k++)

19         for(int i=1; i<=n; i++)

20             for(int j=1; j<=n; j++)

21                 if(map[i][k]!=inf&&map[k][j]!=inf&&map[i][k]+map[k][j]<map[i][j])

22                     map[i][j]=map[i][k]+map[k][j];

23 }

24 

25 void Get_Dp()

26 {

27     for(int i=0; i<=(1<<k); i++)

28         for(int j=0; j<=(1<<k); j++)

29             for(int u=1; u<=n; u++)dp[i][j][u]=inf;

30     dp[0][0][1]=0;

31     for(int state1=0; state1<(1<<k); state1++) {

32         for(int state2=0; state2<(1<<k); state2++) {

33             for(int u=1; u<=n; u++)if(dp[state1][state2][u]<inf) {

34                     for(int i=0; i<k; i++)if(!(state1&(1<<i))) {

35                             int cost=map[u][pos[i]];

36                             if(state2&(1<<i))cost+=f_time[i];

37                             else cost+=time[i];

38                             dp[state1|(1<<i)][state2|Mask[pos[i]]][pos[i]]=min(dp[state1|(1<<i)][state2|Mask[pos[i]]][pos[i]],dp[state1][state2][u]+cost);

39                         }

40                     for(int v=1; v<=n; v++) {

41                         dp[state1][state2|Mask[v]][v]=min(dp[state1][state2|Mask[v]][v],dp[state1][state2][u]+map[u][v]);

42                     }

43                 }

44         }

45     }

46     ans=inf;

47     for(int state=0;state<(1<<k);state++){

48         ans=min(ans,dp[(1<<k)-1][state][1]);

49     }

50 }

51 

52 

53 int main()

54 {

55     int _case,u,v,w,num,t=1;

56     scanf("%d",&_case);

57     while(_case--) {

58         scanf("%d%d%d",&n,&m,&k);

59         for(int i=1; i<=n; i++)

60             for(int j=1; j<=n; j++)map[i][j]=(i==j?0:inf);

61         while(m--) {

62             scanf("%d%d%d",&u,&v,&w);

63             map[u][v]=map[v][u]=min(map[u][v],w);

64         }

65         FILL(Mask,0);

66         for(int i=0; i<k; i++) {

67             scanf("%d%d%d%d",&pos[i],&time[i],&f_time[i],&num);

68             while(num--) {

69                 scanf("%d",&v);

70                 Mask[v]|=(1<<i);

71             }

72         }

73         floyd();

74         Get_Dp();

75         printf("Case #%d: %d\n",t++,ans);

76     }

77     return 0;

78 }
View Code

 

 

你可能感兴趣的:(HDU)