题意:
pure 在玩一个战略类游戏。现在有一个士兵方阵,每一行有若干士兵,每个士兵属于某个兵
种。行的顺序不可改变,且每一行中士兵的顺序也不可改变。但由于每一行都有 C 个位置(C 不
小于任一行的士兵数),她能够安排每行的士兵依次站在某几个位置上。
对于每一个士兵,令其前后左右相邻四个位置上有 v 个和他种类相同的士兵,则 pure 会获得
v 的布阵分数。现在 pure 想知道她最多能够获得多少布阵分数。
分析:
轮廓线DP不扯了就是个板
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXS 65556
#define MAXN 130
#define MAXM 20
using namespace std;
int n,c;
int dp[2][MAXS],ans;
char s[MAXN][MAXM];
int siz[MAXN];
int count(int mask,int x,int id,int num){
int add=0;
if(id!=1)
if((mask&(1<<(id-2)))&&s[x][num]==s[x][num-1])
add++;
int sum=__builtin_popcount(mask>>(id-1));
int num1=siz[x-1]-sum+1;
if((mask&(1<<(id-1)))&&s[x][num]==s[x-1][num1])
add++;
return add;
}
int main(){
freopen("group.in","r",stdin);
freopen("group.out","w",stdout);
SF("%d%d",&n,&c);
for(int i=1;i<=n;i++){
SF("%s",s[i]+1);
siz[i]=strlen(s[i]+1);
}
int now=0;
for(int i=1;i<=n;i++){
for(int mask=0;mask<(1<<c);mask++){
if(__builtin_popcount(mask)==siz[i-1])
dp[now][mask]=dp[now^1][mask];
else
dp[now][mask]=-1;
}
now^=1;
for(int j=1;j<=c;j++){
for(int mask=0;mask<(1<<c);mask++)
dp[now][mask]=0;
for(int mask=0;mask<(1<<c);mask++){
if(dp[now^1][mask]==-1)
continue;
int x=__builtin_popcount(mask%(1<<(j-1)));
if(x!=siz[i])
dp[now][mask|(1<<(j-1))]=max(dp[now][mask|(1<<(j-1))],dp[now^1][mask]+count(mask,i,j,x+1));
dp[now][mask&((1<<c)-1-(1<<(j-1)))]=max(dp[now][mask&((1<<c)-1-(1<<(j-1)))],dp[now^1][mask]);
//PF("{%d %d %d %d}\n",i,j-1,mask,dp[i][j-1][mask]);
}
now^=1;
}
}
for(int mask=0;mask<(1<<c);mask++)
if(__builtin_popcount(mask)==siz[n])
ans=max(ans,dp[now^1][mask]);
PF("%d",ans*2);
}