poj1185(状态压缩DP)

poj1185

题意

给出字母矩阵,只能在字母为 P 的位置放置大炮,

如图所示,每个大炮的射程固定,现在要求尽可能多的放大炮,且使得每个大炮都不在其它大炮的射程内。问最多能放多少。

分析

poj3254
很类似的一道题,但是注意到这道题,放置一个大炮后,不仅影响到与之相邻的下一行,同时对下下一行产生影响,也就是说某一个地点能否存在大炮,取决于它上面两行的状态,那么状态的转移就和上面两行有关,两层循环枚举上面两层的可行状态,判断加上这一层的状态后是否合法(即对于连续的 3 行,每一列最多只能存在一个 1),如果合法,加上这个状态下在这一行最多能放大炮的数量,不断更新最大值。
可以预处理一行的状态,求得同时在这一行最多放几个大炮。

code

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
typedef long long ll;
const int MAXN = (1 << 10) + 10;
int dp[105][MAXN][MAXN];
int num[1 << 10];
string str;
bool check(int j, int s) { // 判断 j 是否是一个可行状态
    return (j | s) == s && (j & (j >> 1)) == 0
                        && (j & (j >> 2)) == 0;
}
void F(int n) {
    vector<int> v;
    if(!n) cout << 0;
    while(n) {
        v.push_back(n & 1);
        n /= 2;
    }
    for(int i = v.size() - 1; i >= 0; i--) {
        cout << v[i];
    }

}
int main() {
    int n, m;
    cin >> n >> m;
    for(int i = 0; i < (1 << m); i++) {
        int k = 0;
        for(int j = 0; j < 11; j++) {
            if(!k) {
                if((i >> j) & 1) {
                    k = 3;
                    num[i]++;
                } else k = 1;
            }
            k--;
        }
    }
    vector<int> vec1, vec2, vec3; // vec2存上一层的可行状态,vec1存上上一层的可行状态
    int ans = 0;
    for(int i = 0; i < n; i++) {
        cin >> str;
        int s = 0;
        for(int j = 0; j < m; j++) {
            if(str[j] == 'P') {
                s |= (1 << j);
            }
        }
        if(i > 1) {
            vec3.clear();
            for(int j = 0; j < (1 << m); j++) {
                if(check(j, s)) {
                    for(int v = 0; v < vec1.size(); v++) {
                        for(int e = 0; e < vec2.size(); e++) {
                            if((j & vec1[v]) == 0 && (j & vec2[e]) == 0 && (vec1[v] & vec2[e]) == 0) { // 保证连续 3 行每一列最多只有一个 1
                                dp[i][j][vec2[e]] = max(dp[i][j][vec2[e]], dp[i - 1][vec2[e]][vec1[v]] + num[j]);
                                ans = max(ans, dp[i][j][vec2[e]]);
                            }
                        }
                    }
                    vec3.push_back(j);
                }
            }
            vec1 = vec2;
            vec2 = vec3;
        } else if(!i) {
            for(int j = 0; j < (1 << m); j++) {
                if(check(j, s)) {
                    dp[i][j][0] = num[j];
                    ans = max(ans, num[j]);
                    vec1.push_back(j);
                }
            }
        } else {
            for(int j = 0; j < (1 << m); j++) {
                if(check(j, s)) {
                    for(int k = 0; k < vec1.size(); k++) {
                        if((j & vec1[k]) == 0) {
                            dp[i][j][vec1[k]] = dp[i - 1][vec1[k]][0] + num[j];
                            ans = max(ans, dp[i][j][vec1[k]]);
                        }
                    }
                    vec2.push_back(j);
                }
            }
        }
    }
    cout << ans << endl;
    return 0;
}
posted @ 2017-06-14 15:22  ftae  阅读(268)  评论(0编辑  收藏  举报