题目给几个字符串,可以给它们添加前导空格,然后排列,计算每一个字符串和前一个字符串相同非空格字符相等的个数,求可能的最大个数。
状态DP:
d[S][i][j]表示已经用的字符串集合S且排列的最后一个是前面带j个空格的字符串i
转移就枚举从什么字符串几个前导0结尾转移过来的。还可以预处理一下各个情况的字符串相同字符个数。时间复杂度大概就O(n2*100+2n*n2*100)。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int d[1<<10][10][10],val[10][10][10][10]; 6 char str[11][11]; 7 int main(){ 8 int n; 9 while(~scanf("%d",&n) && n){ 10 memset(str,0,sizeof(str)); 11 for(int i=0; i<n; ++i){ 12 scanf("%s",str[i]); 13 } 14 memset(val,0,sizeof(val)); 15 for(int i=0; i<n; ++i){ 16 for(int j=0; j<n; ++j){ 17 if(i==j) continue; 18 for(int x=0; x<10; ++x){ 19 for(int y=0; y<10; ++y){ 20 for(int k=max(x,y); str[i][k-x]&&str[j][k-y]; ++k){ 21 if(str[i][k-x]==str[j][k-y]) ++val[i][j][x][y]; 22 } 23 } 24 } 25 } 26 } 27 memset(d,0,sizeof(d)); 28 for(int s=1; s<(1<<n); ++s){ 29 for(int i=0; i<n; ++i){ 30 if(((s>>i)&1)==0) continue; 31 for(int j=0; j<10; ++j){ 32 for(int x=0; x<n; ++x){ 33 if(x==i || ((s>>x)&1)==0) continue; 34 for(int y=0; y<10; ++y){ 35 d[s][i][j]=max(d[s][i][j],d[s^(1<<i)][x][y]+val[i][x][j][y]); 36 } 37 } 38 } 39 } 40 } 41 int res=0; 42 for(int i=0; i<n; ++i){ 43 for(int j=0; j<10; ++j) res=max(res,d[(1<<n)-1][i][j]); 44 } 45 printf("%d ",res); 46 } 47 return 0; 48 }