萌新刚学状压 DP 求调,WA 30 pts

P2704 [NOI2001] 炮兵阵地

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 n=1 的情况也过了,现在就剩 Sub 1 的 6 个点了。


by 50lty12 @ 2023-02-11 13:13:20

@caihaolang 我做的时候只特判了第 1 行的情况,您看下把特判第 2 行的代码删掉行不行


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,找到错误了,合法状态只有几十种,但最大可能到 1023,不能直接用 S 作为第二维,要用 S 在合法状态下的下标作为 f 的第二维。


|