NOI2001 炮兵阵地 - 状压DP

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int INF = (1<<30);
int gra[110][12],n,m,f[110][100][100],s[110],tot,ans,temte[12],temtot;
void print(int k);
void initialization() {
    for(int i=0; i<1<<m; i++) {
        int pre=-1;
        bool flg = true;
        for(int j=0; j<m; j++) 
            if((i>>j) & 1) {
                if(pre>=0 && j-pre<3) { //注意pre>=0,因为最右边第一位可能就是1
                    flg = false;
                    break;
                }
                pre = j;
            }
        if(flg) 
            s[++tot] = i;
    }
    for(int i=1; i<=n; i++) 
        for(int j=1; j<=m; j++) 
            for(int l=1; l<=m; l++) 
                f[i][j][l] = -INF;
}
bool dep(int p, int k) {
    int tem = s[k];
    for(int i=0; i<m; i++) 
        if(!gra[p][m-i] && (tem >> i & 1)) 
            return false;
    return true;
}

void print(int k) {//调试用,输出二进制
     k = s[k];
     temtot = 0;
     for(int i=0; i<m; i++) 
        temte[++temtot] = (k >> i) & 1;
     for(int i=temtot; i>=1; i--) 
        cout <<temte[i];
     cout << endl;
}

int count(int k) {
    int tem = s[k];
    int sum = 0;
    for(int i=0; i<m; i++) 
        if(tem>>i&1) sum++;
    return sum;
}
int main() {
    scanf("%d %d", &n, &m);
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            char ch;
            cin >> ch;
            if(ch == 'P') gra[i][j] = 1;
        }
    }
    initialization();
    f[0][0][0] = 0;
    for(int i=1; i<=n; i++) 
        for(int j=1; j<=tot; j++) 
            for(int k=1; k<=tot; k++) {
                int temp = -INF;
                if(!(s[j] & s[k]) && dep(i,j) && dep(i-1,k) ) {
                    for(int l=1; l<=tot; l++) 
                        if(!(s[j] & s[l])) 
                            temp = max(temp, f[i-1][k][l]);
                    f[i][j][k] = temp + count(j);
                }
            }
    for(int i=1; i<=tot; i++)
        for(int j=1; j<=tot; j++) 
            if(!(s[i] & s[j]) && dep(n,i) && dep(n-1,j))
                ans = max(ans, f[n][i][j]);
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fantasy_world/article/details/80289525