首页 > 代码库 > POJ 1185炮兵阵地
POJ 1185炮兵阵地
解题思路:
简单的状压DP,1表示放炮,预处理出每一行所有两个1间隔不小于2的状态,每一行的状态只和上面两行有关,因此可以枚举这三行的状态,用DP[i][j][k]表示第i行状态为k,第i-1行状态为j的数目,转移方程为dp[i][j][k] = max(dp[i][j][k], dp[i-1][l][j] +count(k));
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <queue> #include <algorithm> #include <set> #include <map> #define LL long long #define FOR(i, x, y) for(int i=x;i<=y;i++) using namespace std; const int MAXNr = 100 + 10; const int MAXNc = (1 << 11); int dp[MAXNr][MAXNr][MAXNr]; int C[MAXNr], state[MAXNc]; char str[MAXNr][MAXNr]; int Map[MAXNr]; int N, M, K; bool judge(int x) { if(x & (x << 1)) return false; if(x & (x << 2)) return false; return true; } int count(int x) { int res = 0; while(x) { if(x & 1) res++; x >>= 1; } return res; } void init() { memset(Map, 0, sizeof(Map)); int r = (1 << M) - 1; K = 0; FOR(i, 0, r) if(judge(i)) state[++K] = i; memset(dp, -1, sizeof(dp)); } int main() { while(scanf("%d%d", &N, &M)!=EOF) { if(N == 0 && M == 0) break; init(); FOR(i, 1, N) scanf("%s", str[i]+1); FOR(i, 1, N) FOR(j, 1, M) if(str[i][j] == 'H') Map[i] = (Map[i] | (1 << (M - j))); FOR(i, 1, K) if(!(state[i] & Map[1])) { dp[1][1][i] = count(state[i]); } FOR(i, 2, N) { FOR(l, 1, K) { if(state[l] & Map[i]) continue; FOR(j, 1, K) { if(state[l] & state[j]) continue; FOR(t, 1, K) { if(state[l] & state[t]) continue; if(dp[i-1][t][j] == -1) continue; dp[i][j][l] = max(dp[i][j][l], dp[i-1][t][j] + count(state[l])); } } } } int ans = 0; FOR(i, 1, N) FOR(j, 1, K) FOR(k, 1, K) ans = max(ans , dp[N][j][k]); printf("%d\n", ans); } return 0; }
POJ 1185炮兵阵地
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。