POJ 1185 炮兵阵地

来源:互联网 发布:网络禁书40百度云 编辑:程序博客网 时间:2024/05/22 04:29

非常有趣的一个问题,也困扰了我一段时间。


利用递归的话由于有大量重复计算的内容,所以可以使用动态规划,获取所有的需要计算的值。


题目内容中存在上两行都对当前行的选择存在影响,所以不同于一般的动态规划。我本来是希望将地图的每两行合并为一行,之后通过动态规划保存在确定上两行的情况下的最优解。不过在最坏情况下会超时,我计算了原先代码运算量为(2500 * 2500 * row)。


在看了某些大大关于状态压缩的文章才明白了。


首先由于地形和炮兵布置方案都只有两种状态,即 “H” 和 “P”  以及 “ 放置”  和 “不放”,所以可以用二进制表示,由于地图最大只有十列,所以最大值为1024(2 ^ 10)。


通过&符号可以实现二进制的 “与”功能,所以只需要用 地图的整数形态 & 方法的整数形态 ==  1 即可知道方法是否可以在地图上放置。 而  方法的整数形态 & 另一个方法即可知道上下行方法是否冲突。


之后是一行不冲突最多有60中可能(包括放置0个炮兵),如果不明白是怎么获得的,可以将下面代码Init函数中的count提出来看。


下面代码用g_lineState[i][j][k]保存第i行,本行方法序号为j,上一行方法序号为k的最优解(由顶至下)倍;

动态规划公式为遍历地图每一行i,本行方法序号j,上行方法序号k,上上行方法序号t,g_lineState[i][j][k] = max(g_lineState[i - 1][k][t] + 本行炮兵数);


新办法的运行时间为(row * 60 * 60 * 60),换算后比原先的代码块20倍;


下面代码的运行时间为188ms


/***********************炮兵阵地time (60 * 60 * 60 * g_row)***********************/#include"iostream"#include"string.h"#include"math.h"using namespace std;//宏定义#define OneLineMax 60 //一行最大可行布置方案//全局变量char g_map[100][10]; //字符地图int g_numMap[100]; //数字地图int g_row; //地图的行int g_col; //地图的列int g_setStyle[OneLineMax]; //布置方案int g_gunCount[OneLineMax]; //每个方案炮兵数目int g_lineState[100][OneLineMax][OneLineMax]; //每行地图最优状态//声明void Init();void DP();//主函数int main(void){Init();//读入地图信息cin >> g_row >> g_col;for(int i = 0; i < g_row; i++){cin >> g_map[i];g_map[i][g_col] = 'H';//将地图转换为整数g_numMap[i] = 0;for(int j = 0; j < 10; j++){if(g_map[i][j] == 'H'){g_numMap[i] += pow(2.0, 9 - j);}}}DP();//打印输出最优解int nowPos = 0;int lastPos = 0;for(int i = 0; i < OneLineMax; i++){for(int j = 0; j < OneLineMax; j++){if(g_lineState[g_row - 1][i][j] > g_lineState[g_row - 1][nowPos][lastPos]){nowPos = i;lastPos = j;}}}cout << g_lineState[g_row - 1][nowPos][lastPos];//system("pause");return 0;}//初始化函数void Init(){//初始化地图状态为‘H’memset(g_map, 'H', sizeof(g_map));//初始化最优状态为0memset(g_lineState, 0, sizeof(g_lineState));//获取所有布置方案并保存int count = 0;g_setStyle[count] = 0;g_gunCount[count++] = 0;for(int i1 = 0; i1 < 10; i1++){int temp1 = pow(2.0, 9 - i1);g_setStyle[count] = temp1;g_gunCount[count++] = 1;for(int i2 = i1 + 3; i2 < 10; i2++){int temp2 = pow(2.0, 9 - i2);g_setStyle[count] = temp1 + temp2;g_gunCount[count++] = 2;for(int i3 = i2 + 3; i3 < 10; i3++){int temp3 = pow(2.0, 9 - i3);g_setStyle[count] = temp1 + temp2 + temp3;g_gunCount[count++] = 3;for(int i4 = i3 + 3; i4 < 10; i4++){int temp4 = pow(2.0, 9 - i4);g_setStyle[count] = temp1 + temp2 + temp3 + temp4;g_gunCount[count++] = 4;}}}}}//动态规划获取最优解void DP(){//设置第一层地图的状态for(int i = 0; i < OneLineMax; i++){//如果当前方案与地形冲突if(g_setStyle[i] & g_numMap[0]){continue;}g_lineState[0][i][0] = g_gunCount[i];}//设置之后几层的状态for(int i = 1; i < g_row; i++){for(int j = 0; j < OneLineMax; j++){//如果方案与地图冲突就跳到下一步if(g_setStyle[j] & g_numMap[i]){memset(g_lineState[i][j], 0, sizeof(g_lineState[i][j]));continue;}for(int k = 0; k < OneLineMax; k++){//如果上行方案与本行方案发生冲突if(g_setStyle[j] & g_setStyle[k]){g_lineState[i][j][k] = 0;continue;}for(int t = 0; t < OneLineMax; t++){//如果上上行方案与本行方案发送冲突if(g_setStyle[j] & g_setStyle[t]){continue;}//判断当前选择是否较优int temp = g_gunCount[j] + g_lineState[i - 1][k][t];if(temp > g_lineState[i][j][k]){g_lineState[i][j][k] = temp;}}}}}}



测试数据


5 4PHPPPPHHPPPPPHPPPHHP
100 10PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP334


0 0