日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

POJ 1185 炮兵阵地 【状压DP】

發(fā)布時(shí)間:2025/5/22 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POJ 1185 炮兵阵地 【状压DP】 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

<題目鏈接>

題目大意:

司令部的將軍們打算在N*M的網(wǎng)格地圖上部署他們的炮兵部隊(duì)。一個(gè)N*M的地圖由N行M列組成,地圖的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下圖。在每一格平原地形上最多可以布置一支炮兵部隊(duì)(山地上不能夠部署炮兵部隊(duì));一支炮兵部隊(duì)在地圖上的攻擊范圍如圖中黑色區(qū)域所示:?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

如果在地圖中的灰色所標(biāo)識(shí)的平原上部署一支炮兵部隊(duì),則圖中的黑色的網(wǎng)格表示它能夠攻擊到的區(qū)域:沿橫向左右各兩格,沿縱向上下各兩格。圖上其它白色網(wǎng)格均攻擊不到。從圖上可見(jiàn)炮兵的攻擊范圍不受地形的影響。?
現(xiàn)在,將軍們規(guī)劃如何部署炮兵部隊(duì),在防止誤傷的前提下(保證任何兩支炮兵部隊(duì)之間不能互相攻擊,即任何一支炮兵部隊(duì)都不在其他支炮兵部隊(duì)的攻擊范圍內(nèi)),在整個(gè)地圖區(qū)域內(nèi)最多能夠擺放多少我軍的炮兵部隊(duì)。

輸入:

第一行包含兩個(gè)由空格分割開(kāi)的正整數(shù),分別表示N和M;?
接下來(lái)的N行,每一行含有連續(xù)的M個(gè)字符('P'或者'H'),中間沒(méi)有空格。按順序表示地圖中每一行的數(shù)據(jù)。N <= 100;M <= 10。

輸出:

僅一行,包含一個(gè)整數(shù)K,表示最多能擺放的炮兵部隊(duì)的數(shù)量。

解題分析:

從形式和數(shù)據(jù)范圍來(lái)看,不難看出是一道狀壓DP的題。因?yàn)榈?i$行與前兩行的狀態(tài)有關(guān),所以我們這里用$dp[i][j][k]$來(lái)表示第$i$行為第$j$種狀態(tài),$k$則表示上一行的狀態(tài)。

#include <cstdio> #include <algorithm> using namespace std;const int MAXR = 110, MAXC = 15, MAXM = 70; #define legal(a,b) a&bint n,m,top; int base[MAXR],state[MAXM],num[MAXM],dp[MAXR][MAXM][MAXM]; //dp[i][j][k],表示第i行,j表示第i行的狀態(tài),k表示第i-1行的狀態(tài) char graph[MAXR][MAXC]; inline bool ok(int x){ //在同一行的角度下,先判斷這個(gè)狀態(tài)是否可行if(x&(x<<1) || x&(x<<2))return false;return true; } inline int Count(int x){ //計(jì)算這個(gè)狀態(tài)下,該行所放士兵的數(shù)量int ans=0;while(x){ans+=x&1;x>>=1;}return ans; } inline void init(){top=0;for(int i=0;i<(1<<m);i++){if(!ok(i))continue;num[top]=Count(i); //記錄每個(gè)狀態(tài)對(duì)應(yīng)士兵的數(shù)量state[top++]=i; //預(yù)處理出初始的所有可行狀態(tài) } } int main(){scanf("%d%d",&n,&m);for(int i=0;i<n;i++){scanf("%s",graph[i]);for(int j=0;j<m;j++)if(graph[i][j]=='H')base[i]+=1<<j;}init();for(int i=0;i<top;i++){ //初始化第一行if(legal(state[i],base[0]))continue;dp[0][i][0]=num[i];}for(int i=0;i<top;i++){ //初始化第二行 ,i表示第二行的狀態(tài)if(legal(state[i],base[1]))continue;for(int j=0;j<top;j++){ //j表示第一行的狀態(tài)if(legal(state[j],base[0]))continue;if(legal(state[i],state[j]))continue;dp[1][i][j]=max(dp[1][i][j],dp[0][j][0]+num[i]);}}for(int r=2;r<n;r++){ //枚舉第r行for(int i=0;i<top;i++){ //第r行的狀態(tài)if(legal(state[i],base[r]))continue;for(int j=0;j<top;j++){ //第r-1行的狀態(tài)if(legal(state[j],base[r-1]))continue;if(legal(state[i],state[j]))continue;for(int k=0;k<top;k++){ //第r-2行的狀態(tài)if(legal(state[k],base[r-2]))continue;if(legal(state[j],state[k]))continue;if(legal(state[i],state[k]))continue;dp[r][i][j]=max(dp[r][i][j],dp[r-1][j][k]+num[i]);}}}}int ans=0;for(int i=0;i<top;i++)for(int j=0;j<top;j++)ans=max(ans,dp[n-1][i][j]); //從最后一行的所有狀態(tài)中挑選一個(gè)最大的printf("%d\n",ans); }

?

轉(zhuǎn)載于:https://www.cnblogs.com/00isok/p/10593748.html

總結(jié)

以上是生活随笔為你收集整理的POJ 1185 炮兵阵地 【状压DP】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。