POJ-1699 Best Sequence 状态压缩DP

  题目链接:http://poj.org/problem?id=1699

  太爽了这题,1AC。容易想到用状态压缩DP来做,f[k][i][j]表示当前 i 状态有 k 个串并且串以 j 结尾的最短串。则 f[k][i][rt]=Min{ f[k][i][rt] , f[k][st][r]+len[j]+g[r][j] }。其中状态 i 用位运算表示所包含的具体的串,1010表示包含串2和4。这里要注意转移方程中的rt,要考虑串包含的情况。

 1 //STATUS:C++_AC_0MS_324KB

 2 #include<stdio.h>

 3 #include<stdlib.h>

 4 #include<string.h>

 5 #include<math.h>

 6 #include<iostream>

 7 #include<string>

 8 #include<algorithm>

 9 #include<vector>

10 #include<queue>

11 #include<stack>

12 #include<map>

13 using namespace std;

14 #define LL __int64

15 #define pii pair<int,int>

16 #define Max(a,b) ((a)>(b)?(a):(b))

17 #define Min(a,b) ((a)<(b)?(a):(b))

18 #define mem(a,b) memset(a,b,sizeof(a))

19 #define lson l,mid,rt<<1

20 #define rson mid+1,r,rt<<1|1

21 const int N=11,INF=0x3f3f3f3f,MOD=10000,STA=8000010;

22 const double DNF=1e13;

23 

24 char s[N][22];

25 int f[2][1<<N][11],len[N],g[N][N],next[2][1<<N],cnt[2],vis[1<<N];

26 int T,n;

27 

28 void getg()

29 {

30     int i,j,k,p;

31     for(i=0;i<n;i++){

32         for(j=0;j<n;j++){

33             for(k=0;k<=len[i];k++){

34                 for(p=k;p<len[i] && p-k<len[j];p++)

35                     if(s[i][p]!=s[j][p-k])break;

36                 if(p==len[i] || p-k==len[j]){

37                     g[i][j]=Min(len[i]-k,len[j]);

38                     break;

39                 }

40             }

41         }

42     }

43 }

44 

45 int main()

46 {

47   //  freopen("in.txt","r",stdin);

48     int i,j,p,st1,k,r,st2,ans,rt;

49     scanf("%d",&T);

50     while(T--)

51     {

52         scanf("%d",&n);

53         for(i=0;i<n;i++){

54             scanf("%s",s[i]);

55             len[i]=strlen(s[i]);

56         }

57         getg();

58 

59         mem(cnt,0);

60         mem(vis,0);

61         for(i=0;i<n;i++){

62             next[0][cnt[0]]=1<<i;

63             f[0][1<<i][i]=len[i];

64             cnt[0]++;

65         }

66         mem(f[p=1],INF);

67         for(i=1;i<n;i++){

68             for(k=0;k<cnt[!p];k++){

69                 st1=next[!p][k];

70                 for(r=0;r<n;r++){

71                     if(st1&(1<<r)){

72                         for(j=0;j<n;j++){

73                             if(st1&(1<<j))continue;

74                             st2=st1|(1<<j);

75                             if(!vis[st2]){

76                                 vis[st2]=1;

77                                 next[p][cnt[p]++]=st2;

78                             }

79                             if(g[r][j]==len[j])rt=r;

80                             else rt=j;

81                             f[p][st2][rt]=Min(f[p][st2][rt],f[!p][st1][r]+len[j]-g[r][j]);

82                         }

83                     }

84                 }

85             }

86             mem(vis,0);

87             cnt[p=!p]=0;

88             mem(f[p],INF);

89         }

90 

91         ans=INF;

92         k=(1<<n)-1;

93         for(i=0;i<n;i++)

94             ans=Min(ans,f[!p][k][i]);

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

96     }

97     return 0;

98 }

 

你可能感兴趣的:(sequence)