刷表枚举要从0 到你要的状态-1啊!!!!;
轮廓线高位,低位(位运算要熟练)
题目:
pure 在玩一个战略类游戏。现在有一个士兵方阵,每一行有若干士兵,每个士兵属于某个兵
种。行的顺序不可改变,且每一行中士兵的顺序也不可改变。但由于每一行都有C 个位置(C 不
小于任一行的士兵数),她能够安排每行的士兵依次站在某几个位置上。
对于每一个士兵,令其前后左右相邻四个位置上有v 个和他种类相同的士兵,则pure 会获得
v 的布阵分数。现在pure 想知道她最多能够获得多少布阵分数。
1.2 Input
第一行包含两个整数R;C,分别表示行数,以及每一行的位置数。
接下来R 行,每行一个由大写字母构成的字符串,同一字母的士兵为同一种类。
1.3 Output
一行一个整数,表示pure 能够获得的最高布阵分数。
1.4 Sample Input
2 5
ABBCD
AC
1.5 Sample Output
6
1.6 Hint
布阵如下:
ABBCD
A__C_
共获得6 分。
1.7 Note
对于20% 的数据,R <= 3;C <= 4;
对于40% 的数据,R <= 16;
对于100% 的数据,R <= 128;C <= 16,字符串长度不超过C。
#include<bits/stdc++.h>
using namespace std;
int cnt[100000],r,c, len[200], ans, dp[2][100000];
char s[130][20];
int main()
{
//freopen("group.in","r",stdin) ;
//freopen("group.out","w",stdout) ;
cin >> r >> c;
for(int i = 1; i <= r; i++)
{
scanf("%s",s[i]+1);
len[i] = strlen(s[i]+1);
}
int ha = (1<<c) - 1;
for(int i = 1; i <= ha; i++)
{
int t = i^(i&(-i));
cnt[i] = cnt[t] + 1;
}
for(int i = 0; i <= c;i++)
s[0][i] = '#';
int pas = 0, now = 1;
for(int i = 0; i < r * c; i++)
{
int hang = i/ c;
int lie = i % c;
if(i == 10)
int haha = 1;
memset(dp[now],0,sizeof(dp[now]));
for(int j = 0; j <= ha; j++)
{
int gao = j >> (c - lie);
int di = j ^ (gao << (c - lie));
int shug = cnt[gao];
int shud = cnt[di];
if(shud > len[hang] || shud + lie < len[hang] || shug > len[hang+1] || shug + c - lie <len[hang+1]) continue;
if(shug < len[hang+1])
{
int tmp = 0;
if((j & 1) && s[hang][len[hang] - shud +1] == s[hang + 1][shug+1]) tmp += 2;
if((j & (1 << (c-1))) && s[hang+1][shug] == s[hang+1][shug+1]) tmp += 2;
dp[now][(j >> 1)|(1<<(c-1))] = max(dp[pas][j] + tmp,dp[now][(j >> 1)|(1<<(c-1))]);
}
dp[now][j >> 1] = max(dp[pas][j] , dp[now][j >> 1]);
}
pas ^= 1;
now ^= 1;
}
for(int i = 0; i <= ha; i++)
{
if(cnt[i] == len[r])
ans = max(ans, dp[pas][i]);
}
cout << ans;
return 0;
}