这个题的意思是第一行给出case数N (1 <= N <= 10),然后给出N个单词,每个一行,当输入不是正整数的时候结束。每个单词最多10个字母。要求的是,按任意顺序排列这些单词,可以在单词前面加任意个空格,使得相邻的单词上下对应的字母数目最多,并输出最多是多少。
先预处理出每两个单词相连所能对应的字母数最多的情况,记录到match[i][j]中。注意在一个单词前面加空格时不能使该单词长度超过另一个,WA了一次。
一共最多10个单词,状压存储状态,然后记忆化搜索即可
#include "stdio.h"
#include "string.h"
int n;
char str[20][20];
int match[20][20];
int dp[1<<15][20];
int index[20];
int Max(int a,int b)
{
if (a<b) return b;
else return a;
}
void cal_match(int a,int b)
{
int i,j,max,sum;
max=0;
for (i=0;str[a][i];i++)
{
sum=0;
for (j=0;str[b][j];j++)
if((i+j<strlen(str[a])) && (str[a][i+j]==str[b][j])) sum++;
max=Max(max,sum);
}
for (i=0;str[b][i];i++)
{
sum=0;
for (j=0;str[a][j];j++)
if((i+j<strlen(str[b])) && (str[b][i+j]==str[a][j])) sum++;
max=Max(max,sum);
}
match[a][b]=match[b][a]=max;
}
int dfs(int aim,int x)
{
int i,sum,status;
status=aim^index[x];
if (status==0) return 0;
if (dp[aim][x]!=-1) return dp[aim][x];
sum=0;
for (i=1;i<=n;i++)
{
if ((status&index[i])>0) sum=Max(sum,dfs(status,i)+match[x][i]);
}
dp[aim][x]=sum;
return sum;
}
int main()
{
int ans,aim,i,j;
while (scanf("%d",&n)!=EOF)
{
if (n<=0) break;
for (i=1;i<=n;i++)
scanf("%s",str[i]);
memset(match,0,sizeof(match));
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (i!=j)
cal_match(i,j);
aim=0;
memset(dp,-1,sizeof(dp));
for (i=1;i<=n;i++)
{
index[i]=1<<(i-1);
dp[index[i]][i]=0;
aim+=index[i];
}
ans=0;
for (i=1;i<=n;i++)
ans=Max(ans,dfs(aim,i));
printf("%d\n",ans);
}
return 0;
}