本文主要是介绍POJ 1185 - 炮兵阵地,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Description
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。
Output
Sample Input
5 4 PHPP PPHH PPPP PHPP PHHP
Sample Output
6
把题意简化一下就是地形对放置炮兵有影响,上一行和上两行对放置炮兵也有影响,要在不受影响的情况下找出放置最多的炮兵数。
这是一道状态压缩的DP问题,至于怎么看出是状态压缩,那就是数据量了。100行10列,如果使用普通的DP还要在考虑上两行的情况,那么肯定超时。所以使用了状态压缩。
base用来存储压缩后的地图,state用来存放不考虑地形的情况下【即只有炮兵之间不能相互攻击到】压缩后的情况,soldier用来存放第num种情况的时候能放多少种炮兵,在这里要注意,state和soldier都是对于每一行来说的,还暂时没有考虑前一行和前两行。
然后初始化第一行和第二行【原因你懂得】。
最后按照状态转移方程进行DP就行了,具体代码看下面:
#include <cstdio>
#include <cstring>int row, col;
int ans[110][70][70];//ans[i][j][k] stands for i-th is state[j], i-1-th is state[k];
char maps[110][20];
int base[110];//every row of maps in number;
int state[70], soldier[70];//state for situation, soldier for num of soldiers;
int num;inline int maxn(int a, int b)
{return a > b ? a : b;
}int main()
{memset(ans, 0, sizeof(ans));memset(base, 0, sizeof(base));memset(state, 0, sizeof(state));memset(soldier, 0, sizeof(soldier));num = 0;//record num of accepted situation that only 2 soldiers cant attk;scanf("%d%d", &row, &col);//read datafor (int i = 0; i < row; ++i){scanf("%s", maps[i]);for (int j = 0; j < col; ++j){if (maps[i][j] == 'H')base[i] += (1<<j);}}for (int i = 0; i < (1<<col); ++i){if ((i & (i<<1)) || (i & (i<<2))) continue;//there r 2 soldiers can attk each otherint sym = i;while (sym)//record num of soldiers{soldier[num] += sym&1;sym = sym >> 1;}state[num++] = i;//record situation}for (int i = 0; i < num; ++i)//initialize ans[0][i][0]{if (base[0] & state[i]) continue;//soldier cant put on mountainans[0][i][0] = soldier[i];}for (int i = 0; i < num; ++i)//initialize ans[1][i][j]{if (base[1] & state[i]) continue;for (int j = 0; j < num; ++j){if (base[0] & state[j]) continue;if (state[i] & state[j]) continue;ans[1][i][j] = maxn(ans[1][i][j], ans[0][j][0] + soldier[i]);}}for (int r = 2; r < row; ++r)//i-th row{for (int i = 0; i < num; ++i)//i-th row situation{if (base[r] & state[i]) continue;for (int j = 0; j < num; ++j)//(i-1)-th situation{if (base[r-1] & state[j]) continue;if (state[j] & state[i]) continue;for (int k = 0; k < num; ++k)//(i-2)-th situation{if (base[r-2] & state[k]) continue;if (state[j] & state[k]) continue;if (state[i] & state[k]) continue;ans[r][i][j] = maxn(ans[r][i][j], ans[r-1][j][k] + soldier[i]);}}}}int ret = 0;for (int i = 0; i < num; ++i)for (int j = 0; j < num; ++j)ret = maxn(ret, ans[row-1][i][j]);printf("%d\n", ret);return 0;
}
PS.一开始自己写就是不过,后来借鉴了一位大神的代码才知道自己存状态的情况考虑的优点不对。
大神在这→戳这里
PSS.POJ的中文题,好幸福TUT
这篇关于POJ 1185 - 炮兵阵地的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!