//輸出最大的與前一個字符相同的個數之和
//184K 0MS
//主要要理解是狀態壓縮DP,狀態是是否選擇了該字符
//並且保存狀態時候因爲字符之間有順序,所有需要保存最後一個字符
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define MAXN 12
static int N;
static char words[MAXN][MAXN];
static int len[MAXN][MAXN];
static int dp[1050][MAXN];//表示是否有該狀態以及當前狀態下最後一個字符
static int calcNums(int i,int j)
{
int k1,k2;
k1 = k2 = 0;
int len1 = strlen(words[i]);
int len2 = strlen(words[j]);
int ret = -1;
for (k1=0;k1<len2;++k1)
{
int tmp = 0;
int k3;
for (k2=k1,k3=0;k2<len2&&k3<len1;++k2,++k3)
if (words[i][k3]==words[j][k2])tmp++;
if (tmp>ret)
ret = tmp;
}
for (k1=0;k1<len1;++k1)
{
int tmp = 0;
int k3;
for (k2=k1,k3=0;k2<len1&&k3<len2;++k2,++k3)
if (words[i][k2]==words[j][k3])tmp++;
if (tmp>ret)
ret = tmp;
}
return ret;
}
static void init()
{
memset(len,0,sizeof(len));
for (int i=0;i<N;++i)
{
for (int j=i+1;j<N;++j)
{
len[i][j] = len[j][i] = calcNums(i,j);
}
}
}
static void DP()
{
memset(dp,0,sizeof(dp));
for (int s=0;s<(1<<N)-1;++s)
{
for (int i=0;i<N;++i)//選擇當前狀態的最後一個字符
{
if(s&(1<<i))//如果有該狀態
for (int j=0;j<N;++j)
{
if (i!=j&&(s&(1<<j))==0)
{
dp[s|(1<<j)][j] = max(dp[s|(1<<j)][j],dp[s][i]+len[i][j]);
}
}
}
}
int ans = 0;
for (int i=0;i<N;++i)
{
if (dp[(1<<N)-1][i]>ans)
ans = dp[(1<<N)-1][i];
}
printf("%d\n",ans);
}
int main()
{
while(scanf("%d",&N)&&N)
{
for (int i=0;i<N;++i)
scanf("%s",words[i]);
init();
DP();
}
return 0;
}
poj2817狀態壓縮DP
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.