poj 1185 NYOJ 85 炮兵阵地(状态压缩dp)
生活随笔
收集整理的這篇文章主要介紹了
poj 1185 NYOJ 85 炮兵阵地(状态压缩dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
炮兵陣地
時間限制:2000?ms ?|? 內存限制:65535?KB 難度:6 描述如果在地圖中的灰色所標識的平原上部署一支炮兵部隊,則圖中的黑色的網格表示它能夠攻擊到的區域:沿橫向左右各兩格,沿縱向上下各兩格。圖上其它白色網格均攻擊不到。從圖上可見炮兵的攻擊范圍不受地形的影響。
現在,將軍們規劃如何部署炮兵部隊,在防止誤傷的前提下(保證任何兩支炮兵部隊之間不能互相攻擊,即任何一支炮兵部隊都不在其他支炮兵部隊的攻擊范圍內),在整個地圖區域內最多能夠擺放多少我軍的炮兵部隊。 輸入
接下來每組測試數據的第一行包含兩個由空格分割開的正整數,分別表示N和M; 接下來的N行,每一行含有連續的M個字符('P'或者'H'),中間沒有空格。按順序表示地圖中每一行的數據。0<=N <= 100;0<=M <= 10。
分析:dp[i][j][k]表示排列到第i行,第i-1行的狀態為s[j],第i-2行的狀態為s[k]時,最多可以放置多少個炮兵。
則dp[i][j][k] = max(dp[i][j][k], dp[i-1][j][k] +num[i])。第一行和第二行特殊處理。
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 105; int Map[N]; int dp[N][65][65]; //dp[i][j][k]表示放第i行時,第i-1行為第j個狀態,第i-2行為第k個狀態最多可以放多少個炮兵int s[N], num[N]; int n, m, p;bool check(int x) { //判斷本行的炮兵是否互相攻擊if(x & (x >> 1)) return false;if(x & (x >> 2)) return false;return true; }int Count(int x) { //計算狀態為x時可以放多少個炮兵int i = 1, ans = 0;while(i <= x) {if(x & i) ans++;i <<= 1;}return ans; }void Init() {p = 0;memset(s, 0, sizeof(s));memset(num, 0, sizeof(num));for(int i = 0; i < (1 << m); i++) { //預處理出合法狀態if(check(i)) {s[p] = i;num[p++] = Count(i);}} }int main() {char ch;int T;scanf("%d", &T);while(T--) {scanf("%d%d", &n, &m);if(!n && !m) {printf("0\n");continue;}memset(dp, 0, sizeof(dp));memset(Map, 0, sizeof(Map));for(int i = 0; i < n; i++) {for(int j = 0; j < m; j++) {cin >> ch;if(ch == 'H')Map[i] = Map[i] | (1 << (m - 1 - j)); //P為0,H為1}}Init(); // printf("p = %d\n", p); // for(int i = 0; i < p; i++) { // printf("s[%d] = %d, num[%d] = %d\n", i, s[i], i, num[i]); // }for(int i = 0; i < p; i++) { //求第一行最多放多少if(!(Map[0] & s[i]))dp[0][i][0] = num[i];}for(int i = 0; i < p; i++) { //前兩行最多放多少if(!(Map[1] & s[i])) {for(int j = 0; j < p; j++) {if((!(s[i] & s[j]))) {dp[1][i][j] = max(dp[1][i][j], dp[0][j][0] + num[i]);}}}}for(int r = 2; r < n; r++) { //枚舉行數for(int i = 0; i < p; i++) { //當前行的狀態if(!(s[i] & Map[r])) {for(int j = 0; j < p; j++) { //上一行的狀態if(!(s[j] & Map[r-1])) {if(!(s[i] & s[j])) {for(int k = 0; k < p; k++) { //上上一行的狀態if(!(s[k] & Map[r-2])) {if(!(s[j] & s[k])) {if(!(s[i] & s[k])) {dp[r][i][j] = max(dp[r][i][j], dp[r-1][j][k] + num[i]);}}}}}}}}}}int ans = 0;for(int i = 0; i < p; i++) {for(int j = 0; j < p; j++) {if(ans < dp[n-1][i][j])ans = dp[n-1][i][j];}}printf("%d\n", ans);}return 0; }總結
以上是生活随笔為你收集整理的poj 1185 NYOJ 85 炮兵阵地(状态压缩dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里工程师是如何系统化地总结缓存相关知识
- 下一篇: hdu 1565 方格取数(1)(状态压