一道轮廓线+刷表的题

刷表枚举要从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;
} 

猜你喜欢

转载自blog.csdn.net/Bluelanzhan/article/details/82939230
今日推荐