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 }

 

posted @ 2013-04-10 00:34  zhsl  阅读(510)  评论(0编辑  收藏  举报