非常有趣的乙個問題,也困擾了我一段時間。
利用遞迴的話由於有大量重複計算的內容,所以可以使用動態規劃,獲取所有的需要計算的值。
題目內容中存在上兩行都對當前行的選擇存在影響,所以不同於一般的動態規劃。我本來是希望將地圖的每兩行合併為一行,之後通過動態規劃儲存在確定上兩行的情況下的最優解。不過在最壞情況下會超時,我計算了原先**運算量為(2500 * 2500 * row)。
在看了某些大大關於狀態壓縮的文章才明白了。
首先由於地形和炮兵布置方案都只有兩種狀態,即 「h」 和 「p」 以及 「 放置」 和 「不放」,所以可以用二進位制表示,由於地圖最大只有十列,所以最大值為1024(2 ^ 10)。
通過&符號可以實現二進位制的 「與」功能,所以只需要用 地圖的整數形態 & 方法的整數形態 == 1 即可知道方法是否可以在地圖上放置。 而 方法的整數形態 & 另乙個方法即可知道上下行方法是否衝突。
下面**用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)
} }dp();
//列印輸出最優解
int nowpos = 0;
int lastpos = 0;
for(int i = 0; i < onelinemax; i++)
}} cout << g_linestate[g_row - 1][nowpos][lastpos];
//system("pause");
return 0;
}//初始化函式
void init()
}} }
}//動態規劃獲取最優解
void dp()
g_linestate[0][i][0] = g_guncount[i];
} //設定之後幾層的狀態
for(int i = 1; i < g_row; i++)
for(int k = 0; k < onelinemax; k++)
for(int t = 0; t < onelinemax; t++)
//判斷當前選擇是否較優
int temp = g_guncount[j] + g_linestate[i - 1][k][t];
if(temp > g_linestate[i][j][k])}}
} }}
測試資料
5 4phpp
pphh
pppp
phpp
phhp
100 10pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
pppppppppp
334
poj 1185 炮兵陣地
題目鏈結 題意 在n m的網格地圖上部署炮兵部隊。地圖的每一格可能是山地 用 h 表示 也可能是平原 用 p 表示 如下圖。在每一格平原地形上最多可以布置一支炮兵部隊 山地上不能夠部署炮兵部隊 一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域所示 如果在地圖中的灰色所標識的平原上部署一支炮兵部隊,則圖中...
POJ 1185 炮兵陣地
include include include include include include include include include include include include include include define sz v int v size define rep i,n ...
POJ 1185 炮兵陣地
狀態壓縮專題第一題,自己想了很久,最終還是以別人的 為模板寫的。dp共三維,一維是行數,一維是前一行狀態,一維是前第二行狀態。ps 直接開三維太大,用s陣列記錄下所有可能出現的情況,大大減少時間和空間。include include include includeusing namespace st...