http://www.cnblogs.com/dream-wind/archive/2012/07/19/2599046.html
题意: 有 n 个字符串,可以改变上下顺序,可以在每个单词前加 任意的空格,计算所有单词叠在一起后每一行与上一行相应位置相同的字符数之和,找出最大和。
分析: 两两字符串之间可以用 l *l 的算法计算出最大的连续相同的字符数,由于单词前可以加任意的空格数,所以单词的上下顺序不影响结果,由于字符串的长度最大为10 ,总的个数最多为10,所以可以枚举所有状态,找出最大值。
#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
int max(int a,int b)
{
return a>b?a:b;
}
int dp[1<<12][12];
int g[12][12];
int c_s(char *s1,char *s2) // 最长公共连续子串
{
int tot=0;
int tmp,i,j;
int len1=strlen(s1);
int len2=strlen(s2);
for(i=0;i<11;i++)
{
tmp=0;
for(j=0;j<len1&&i+j<len2;j++)
tmp+=(s1[j]==s2[i+j]);
tot=max(tot,tmp);
}
return tot;
}
int main()
{
//freopen("D:ce.txt","r",stdin);
int st,stat,i,j,k,x,y,n;
char s[12][12];
while(scanf("%d",&n),n)
{
st=(1<<n)-1;
for(i=0;i<n;i++)
scanf("%s",s[i]);
for(i=0;i<n;i++)
for(j=0;j<i;j++)
g[i][j]=g[j][i]=max(c_s(s[i],s[j]),c_s(s[j],s[i]));
memset(dp,0xff,sizeof(dp));
for(i=0;i<n;i++)
dp[1<<i][i]=0;
int stat;
for(i=1;i<st;i++)
for(j=0;j<n;j++)
{
if(dp[i][j]<0) // 状态 i 中不包含 j 这个串
continue;
for(k=0;k<n;k++)
{
if(i&(1<<k))//很像那个tsp的那个状态压缩dp
continue; // 状态 i 中包含了 第 k 个串
stat=i+(1<<k);//从当前状态枚举下一个状态。
dp[stat][k]=max(dp[stat][k],dp[i][j]+g[j][k]);//把k作为最下面的串
}
}
int res=0;
for(i=0;i<n;i++)
res=max(res,dp[st][i]);
printf("%d\n",res);
}
return 0;
}
本文介绍了一个算法问题,即如何通过调整多个字符串的排列顺序及在每个单词前添加任意数量的空格来最大化所有字符串堆叠后的相同字符总数。文中详细解释了算法思路,并提供了完整的C语言实现代码。
1870

被折叠的 条评论
为什么被折叠?



