chlchl @ 2023-02-11 12:27:08
只 A 了 #1,#2,#9……
思路是先预处理所有合法状态,然后再 DP,不会爆空间。
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int N = 100 + 10;
const int SS = 200 + 10;
int n, m, f[N][SS][SS];
char g[N][15];
vector<int> st[N];
bool check1(int x, int S){
for(int i=0;i<m;i++)
if(((S >> i) & 1) && (g[x][i] == 'H'))
return 0;
for(int i=0;i<m-2;i++)
if(((S >> i) & 1) && (((S >> (i + 1)) & 1) || ((S >> (i + 2)) & 1)))
return 0;
if(((S >> (m - 2)) & 1) && (((S >> (m - 1)) & 1)))
return 0;
return 1;
}
bool check2(int S1, int S2, int S3){
for(int i=m-1;i>=0;i--)
if(((S3 >> i) & 1) && (((S2 >> i) & 1) || ((S1 >> i) & 1)))
return 0;
return 1;
}
int main(){
scanf("%d%d", &n, &m);
for(int i=1;i<=n;i++)
scanf("%s", g[i]);
int all = (1 << m) - 1;
for(int i=1;i<=n;i++){
for(int S=0;S<=all;S++)
if(check1(i, S))
st[i].push_back(S);
}
for(int S: st[1])
f[1][S][0] = __builtin_popcount(S);
for(int S: st[2]){
int d = __builtin_popcount(S);
for(int S1: st[1])
if(check2(0, S1, S))
f[2][S][S1] = max(f[2][S][S1], f[1][S1][0] + d);
}
for(int i=3;i<=n;i++){
for(int S: st[i]){
int d = __builtin_popcount(S);
for(int S1: st[i - 1]){
for(int S2: st[i - 2]){
if(check2(S2, S1, S))
f[i][S][S1] = max(f[i][S][S1], f[i - 1][S1][S2] + d);
}
}
}
}
int ans = 0;
for(int S: st[n])
for(int S1: st[n - 1])
ans = max(ans, f[n][S][S1]);
printf("%d\n", ans);
return 0;
}
by chlchl @ 2023-02-11 12:29:53
发现了一个错误,check2
中没有判断上一行和上两行有没有冲突,但加上之后只多对了一个点。
by chlchl @ 2023-02-11 12:36:00
and then
by 50lty12 @ 2023-02-11 13:13:20
@caihaolang 我做的时候只特判了第
by chlchl @ 2023-02-11 14:21:34
@c20210750 一样的……
by allenchoi @ 2023-02-11 14:54:19
@caihaolang 还在卷啊 你们不用开学考试??
by chlchl @ 2023-02-11 14:54:47
@allenchoi 开学考试跟卷 OI 有啥关系\fad
by allenchoi @ 2023-02-11 16:22:27
@caihaolang 我在复习(历史甚至啥都没背(悲((((((((((((((((
by chlchl @ 2023-02-11 18:59:56
6,找到错误了,合法状态只有几十种,但最大可能到