HDU 4539 郑厂长系列故事——排兵布阵 && POJ 1185 炮兵阵地 (状态DP)
2014-03-13 17:42
337 查看
郑厂长系列故事——排兵布阵
Problem Description郑厂长不是正厂长
也不是副厂长
他根本就不是厂长
事实上
他是带兵打仗的团长
一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。
Input
输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。
Output
请为每组数据计算并输出最多能安排的士兵数量,每组数据输出一行。
Sample Input
6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Sample Output
2
每一行的状态只与前面两行的状态有关,每行可以压缩为二进制的集合,设状态dp[i][j][k]为第i行为集合j,第i-1行为集合k,
得出状态方程dp[i][j][k] = max{dp[i-1][k][r]+cnt[j] | 状态i,j,k要能够共存}
对于每一行可能出现的组合,可以先预处理出每一种有效状态。
int dp[2][200][200] ; //dp[row][i][j] ,(截止到)row行状态为第i种,row-1行状态为第j种,的最大人数 int cannot[101] ; int N , M ; int ok(int x){ //同行 if(x & (x<<2)) return 0 ; if(x & (x>>2)) return 0 ; return 1 ; } int Count(int x){ //状态x的人数 int sum = 0 ; while(x){ if(x&1) sum++ ; x>>=1 ; } return sum ; } //求基本状态,与对应的人数 void get_all_states(vector<int> &states , vector<int> &people){ int i ; states.clear() ; people.clear() ; for(i = 0 ; i < (1<<M) ; i++){ if(ok(i)){ states.push_back(i) ; people.push_back(Count(i)) ; } } } int DP(){ int i , j , k ,row , sum = 0 ; vector<int> states ; vector<int> people ; get_all_states(states , people) ; memset(dp , -1 , sizeof(dp)) ; for(i = 0 ; i < states.size() ; i++){ if(states[i] & cannot[1]) continue ; dp[1][i][0] = people[i]; //初值 } for(row = 2 ; row <= N ; row++){ for(i = 0 ; i < states.size() ; i++){ if(states[i] & cannot[row]) continue ; for(j = 0 ; j < states.size() ; j++){ if(states[j] & cannot[row-1]) continue ; if(states[i] & (states[j]<<1)) continue ; if(states[i] & (states[j]>>1)) continue ; for(k = 0 ; k < states.size() ; k++){ if(states[k] & cannot[row-2]) continue ; if(states[i] & states[k]) continue ; if(states[j] & (states[k]<<1)) continue ; if(states[j] & (states[k]>>1)) continue ; if(dp[(row-1)&1][j][k] == -1) continue ; dp[row&1][i][j] = max(dp[row&1][i][j] , dp[(row-1)&1][j][k] + people[i]) ; } } } } for(i = 0 ; i < states.size() ; i++) for(j = 0 ; j < states.size() ; j++) sum = max(sum , dp[N&1][i][j]) ; return sum ; } int main(){ int i , j , x ; while(cin>>N>>M){ memset(cannot , 0 , sizeof(cannot)) ; for(i = 1 ; i <= N ; i++){ for(j = 0 ; j < M ; j++){ cin>>x ; if(!x) cannot[i] |= (1<<j) ; } } cout<<DP()<<endl ; } return 0 ; }
炮兵阵地
Description
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input
第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。
Output
仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。
Sample Input
5 4 PHPP PPHH PPPP PHPP PHHP
Sample Output
6
int N , M ; int dp[101][70][70] ; int cannot[101] ; int ok(int x){ if(x & (x<<1)) return 0 ; if(x & (x<<2)) return 0 ; if(x & (x>>1)) return 0 ; if(x & (x>>2)) return 0 ; return 1 ; } int Count(int x){ int sum = 0 ; while(x){ sum += (x&1) ; x >>= 1 ; } return sum ; } void get_all_states(vector<int> &states , vector<int> &people){ states.clear() ; people.clear() ; for(int i = 0 ; i < (1<<M) ; i++){ if(ok(i)){ states.push_back(i) ; people.push_back(Count(i)) ; } } } int DP(){ int i , j , k , row , ans = 0 ; memset(dp , 0 , sizeof(dp)) ; vector<int> states , people ; get_all_states(states , people) ; for(i = 0 ; i < states.size() ; i++){ if(states[i] & cannot[1]) continue ; dp[1][i][0] = people[i] ; } for(row = 2 ; row <= N ; row++){ for(i = 0 ; i < states.size() ; i++){ if(states[i] & cannot[row]) continue ; for(j = 0 ; j < states.size() ; j++){ if(states[j] & cannot[row-1]) continue ; if(states[i] & states[j]) continue ; for(k = 0 ; k < states.size() ; k++){ if(states[i] & states[k]) continue ; if(states[j] & states[k]) continue ; if(dp[row-1][j][k] == -1) continue ; dp[row][i][j] = max(dp[row][i][j] , dp[row-1][j][k] + people[i]) ; } } } } for(i = 0 ; i < states.size() ; i++) for(j = 0 ; j < states.size() ; j++) ans = max(ans , dp [i][j]) ; return ans ; } int main(){ string s ; while(cin>>N>>M){ memset(cannot , 0 , sizeof(cannot)) ; for(int i = 1 ; i <= N ; i++){ cin>>s ; for(int j = 0 ; j < M ; j++){ if(s[j] == 'H') cannot[i] |= (1<<j) ; } } cout<<DP()<<endl ; } return 0 ; }
相关文章推荐
- POJ 1185 炮兵阵地 HDU 4539 郑厂长系列故事——排兵布阵
- poj 1185 & hdu 4539(状态压缩DP)
- HDU 4539 郑厂长系列故事——排兵布阵(状态压缩dp)
- hdu 4539 郑厂长系列故事——排兵布阵 状态压缩+dp;
- hdu 4539 郑厂长系列故事——排兵布阵(状态压缩dp)
- hdu 4539 郑厂长系列故事——排兵布阵 (状态压缩dp)
- hdu 4539 郑厂长系列故事——排兵布阵(状态压缩dp)
- HDU 4539 郑厂长系列故事——排兵布阵 (状态压缩DP)
- hdu 4539 郑厂长系列故事——排兵布阵(状态压缩DP)
- hdu 4539 郑厂长系列故事——排兵布阵 状态压缩dp
- poj 1185 && NYOJ 85 炮兵阵地(状态压缩dp)
- 【状态压缩DP】 HDU 4539 郑厂长系列故事——排兵布阵
- hdu-4539-郑厂长系列故事――排兵布阵 状态压缩dp
- poj 1185 炮兵阵地 状态压缩dp
- poj 1185 炮兵阵地 (压缩状态DP)
- 【DP】 HDU 4539 郑厂长系列故事——排兵布阵 状压
- HDU 4529 郑厂长系列故事——N骑士问题(dp,状态压缩)
- POJ 1185 炮兵阵地(状态压缩dp)
- POJ 1185 炮兵阵地(状态压缩DP)
- poj 1185 炮兵阵地 (状态压缩 dp)