司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队,一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H"
表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
题目链接:http://poj.org/problem?id=1185
#include <iostream> #include <cstring> using namespace std; #define MAX_SIZE 110 int graph[MAX_SIZE]; int DP[MAX_SIZE][MAX_SIZE][MAX_SIZE]; // DP[raw][i][j] : 在第 raw 行状态为 i, 第 raw - 1 行状态为 j 的情况 int pointer, state_stack[MAX_SIZE], ones_num[MAX_SIZE]; // 判断该状态左右相邻两个单位是否有炮兵冲突 bool isReasonableState( int state ){ if( state & ( state << 1 ) ) return false; if( state & ( state << 2 ) ) return false; return true; } // 计算比特位里的 1 的个数 int getOnesNum( int state ){ int num = 0; while( state > 0 ){ if( state & 1 ) num++; state >>= 1; } return num; } // 预处理,统计下所有“行”摆放炮兵的合法状态 void pretreatment( int cols ){ int max_state = ( 1 << cols ) - 1; for( int state = 0; state <= max_state; ++state ){ if( isReasonableState( state ) ){ state_stack[pointer] = state; ones_num[pointer] = getOnesNum( state ); pointer++; } } } int main(){ memset( DP, -1, sizeof( DP ) ); memset( graph, 0, sizeof( graph ) ); pointer = 0; int raws, cols; cin >> raws >> cols; pretreatment( cols ); for( int raw = 0; raw < raws; ++raw ){ for( int col = 0; col < cols; ++col ){ char c; cin >> c; if( c == 'H' ) graph[raw] |= ( 1 << col ); } } for( int p = 0; p < pointer; ++p ) if( !( state_stack[p] & graph[0] ) ) DP[0][p][0] = ones_num[p]; for( int raw = 1; raw < raws; ++raw ){ for( int raw_p = 0; raw_p < pointer; ++raw_p ){ if( state_stack[raw_p] & graph[raw] ) continue; for( int raw_p_ = 0; raw_p_ < pointer; ++raw_p_ ){ if( state_stack[raw_p] & state_stack[raw_p_] ) continue; for( int raw_p__ = 0; raw_p__ < pointer; ++raw_p__ ){ if( state_stack[raw_p] & state_stack[raw_p__] ) continue; if( DP[raw - 1][raw_p_][raw_p__] == -1 ) continue; DP[raw][raw_p][raw_p_] = max( DP[raw][raw_p][raw_p_], DP[raw - 1][raw_p_][raw_p__] + ones_num[raw_p] ); } } } } int ans = 0; for( int raw_p = 0; raw_p < pointer; ++raw_p ) for( int raw_p_ = 0; raw_p_ < pointer; ++raw_p_ ) ans = max( ans, DP[raws - 1][raw_p][raw_p_] ); cout << ans << endl; return 0; }
状态压缩动态规划 -- 炮兵阵地,布布扣,bubuko.com
原文地址:http://blog.csdn.net/pandora_madara/article/details/35787469