-
B - 炮兵阵地
- POJ - 1185
- 对于原始的矩阵,我们用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; }
B - 炮兵阵地 POJ - 状压DP
猜你喜欢
转载自blog.csdn.net/BePosit/article/details/83067739
今日推荐
周排行