记录编号 378008 评测结果 AAAAAAAAAA
题目名称 [NOI 2001]炮兵阵地 最终得分 100
用户昵称 GravatarRapiz 是否通过 通过
代码语言 C++ 运行时间 0.260 s
提交时间 2017-03-02 20:03:39 内存使用 1.72 MiB
显示代码纯文本
#include <cstdio>
#include <algorithm>
#define file(x) "cannon." #x
const int N = 61;
int n, m, f[101][N][N], num, s[N], ans, rm[101];
char buf[11];
inline int set(int s, int p, int v) {
	if (v) return s|(1 << p - 1);
	else return s & ~(1 << p - 1);
}
inline int get(int s, int p) {return (s<<p - 1)&1;}
void dfs(int c, int ss) {
	if (c > m) s[++num] = ss;
	else dfs(c + 1, ss), dfs(c + 3, set(ss, c, 1));
}
void print(int x) {for (int i = 1; i <= m; i++) printf("%d", x&1), x>>=1;}
int main() {
	freopen(file(in), "r", stdin);
	freopen(file(out), "w", stdout);
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%s", buf + 1);
		for (int j = 1; j <= m; j++) rm[i] = set(rm[i], j, buf[j] == 'H');
	}
	dfs(1, 0);
	for (int i = 1; i <= n; i++) {
		for (int s1 = 1; s1 <= num; s1++) if (!(s[s1]&rm[i]))
			for (int s2 = 1; s2 <= num; s2++) if (!(s[s2]&rm[i - 1]) && !(s[s1]&s[s2]))
				for (int s3 = 1; s3 <= num; s3++) if (!(s[s2]&s[s3]) && !(s[s1]&s[s3])) {
					if (i > 2 && (s[s3]&rm[i - 2])) continue; 
					int cc = __builtin_popcount(s[s1]);
					f[i][s1][s2] = std::max(f[i - 1][s2][s3] + cc, f[i][s1][s2]);
					ans = std::max(ans, f[i][s1][s2]);
				}
	}
	printf("%d\n", ans);
}