炮兵陣地 POJ
阿新 • • 發佈:2018-12-15
- 對於原始的矩陣,我們用0來表示可以放置炮兵,即對應圖中的P,這樣每一行都有一個可以放置炮兵的狀態,存到row[N]中,用來check該行的狀態是否合法。
- 由於當前行和前兩行有關係,所以得用3維矩陣來儲存一個狀態下最多的炮兵個數,用dp[i][curst][prest]表示當前第i行狀態對curst,前一行狀態為prest的最大炮兵數。
- 轉移方程為dp[i][curst][prest]=max{dp[i-1][prest][preprest]},這樣求到最後一行之後,答案就是最後一行所有狀態中最大的那個。程式初始化的時候需要對第一行
- 進行預處理,設定dp[0][st][0]=st合法&st中1的個數。這樣進行下面的計算的時候,由於0狀態肯定是和所有狀態相容的,所以就不會影響計算結果。
-
#include<iostream> #include<stdio.h> using namespace std; #define maxn 111 #define judge(a,b) a&b int row[maxn],m,n; int legal[maxn]; int dp[maxn][maxn][maxn]; int num[maxn],cnt; char str[15]; int cal(int x) { int rng=0; while(x) { x&=(x-1); rng++; } return rng; } int main() { scanf("%d%d",&n,&m); for(int i=0; i<n; i++) { scanf("%s",str); for(int j=0; j<m; j++) { if(str[j]=='H') row[i]+=(1<<j); } } for(int i=0; i<(1<<m); i++) { if(judge(i,i<<1)||judge(i,i<<2))continue; num[cnt]=cal(i); legal[cnt++]=i; } for(int i=0; i<cnt; i++) { if(judge(legal[i],row[0]))continue; dp[0][i][0]=num[i]; } for(int r=1; r<n; r++) for(int i=0; i<cnt; i++) { if(judge(legal[i],row[r]))continue; for(int j=0; j<cnt; j++) { if(judge(legal[j],row[r-1]))continue; if(judge(legal[i],legal[j]))continue; for(int k=0; k<cnt; k++) { if(judge(legal[k],row[r-2]))continue; if(judge(legal[i],legal[k]))continue; if(judge(legal[j],legal[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<cnt; i++) for(int j=0; j<cnt; j++) ans=max(ans,dp[n-1][i][j]); printf("%d\n",ans); return 0; }