hdu 4640(状压dp)

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

思路:f[i][j]表示一个人状态i下走到j的最小花费,dp[i][j]表示i个人在状态j下的最下花费。首先我们可以一遍bfs求出f[i][j],然后通过f[i][j]得到dp[1][i],最后就是更新dp[i][j]了。

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<queue>

 6 using namespace std;

 7 #define inf 1<<30

 8 typedef pair<int,int>PP;

 9 

10 int map[20][20];

11 int f[1<<18][20];//派一个人去,在某状态下到达点v的最小花费

12 int dp[4][1<<18];//派i个人去,在某状态的最小花费

13 bool mark[1<<18][20];

14 int n,m,S,ans;

15 

16 void bfs()

17 {

18     queue<PP>que;

19     que.push(make_pair(0,0));

20     memset(mark,false,sizeof(mark));

21     for(int i=0;i<(1<<n);i++)

22         for(int j=0;j<n;j++)f[i][j]=inf;

23     f[0][0]=0;

24     while(!que.empty()){

25         PP p=que.front();

26         que.pop();

27         int s=p.first,u=p.second;

28         mark[s][u]=false;

29         for(int i=0;i<n;i++){

30             if(map[u][i]<inf&&f[s|(1<<i)][i]>f[s][u]+map[u][i]){

31                 f[s|(1<<i)][i]=f[s][u]+map[u][i];

32                 if(!mark[s|(1<<i)][i]){

33                     mark[s|(1<<i)][i]=true;

34                     que.push(make_pair(s|(1<<i),i));

35                 }

36             }

37         }

38     }

39 }

40 

41 void Solve()

42 {

43     for(int i=1;i<=3;i++)

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

45     for(int i=0;i<(1<<n);i++)

46         for(int j=0;j<n;j++)dp[1][i]=min(dp[1][i],f[i][j]);

47     for(int i=2;i<=3;i++){

48         for(int j=0;j<(1<<n);j++){

49             //枚举子集

50             for(int k=j;k;k=(k-1)&j){

51                 dp[i][j]=min(dp[i][j],max(dp[1][k|1],dp[i-1][(j^k)|1]));

52             }

53         }

54     }

55     ans=inf;

56     for(int i=1;i<=3;i++)

57         for(int j=0;j<(1<<n);j++)if((j&S)==S)ans=min(ans,dp[i][j]);

58     if(ans==inf)ans=-1;

59     printf("%d\n",ans);

60 }

61 

62 int main()

63 {

64     int _case,u,v,w,k,t=1;

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

66     while(_case--){

67         scanf("%d%d",&n,&m);

68         for(int i=0;i<=n;i++)

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

70         while(m--){

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

72             u--,v--;

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

74         }

75         S=0;

76         scanf("%d",&k);

77         while(k--){

78             scanf("%d",&u);

79             u--;

80             S|=(1<<u);

81         }

82         bfs();

83         printf("Case %d: ",t++);

84         Solve();

85     }

86     return 0;

87 }

88 

89 

90 

91             
View Code

 

 

你可能感兴趣的:(HDU)