2019.9.1 炮兵阵地
Posted qxds
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019.9.1 炮兵阵地相关的知识,希望对你有一定的参考价值。
明显状压dp 用dp[i][j][k]记录前i行最后一行状态编号是j且倒数第二行状态编号是k最多能放几个
所以我们先初始化dp[1]和dp[2]
其中dp[1][j][0]=bj[1][j] 因为第0行可以当做没选
dp[2][j][k]=bj[1][j]+bj[2][k] bj数组的意义同下文
则当i>2时 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+bj[i][j])
其中l是枚举的倒数第三行的状态编号,bj[i][j]表示第i行的第j个状态放了多少个
上代码
#include<iostream> #include<cstdio> #include<cstring> #define int long long using namespace std; int num[105][(1<<10)+1],bj[105][(1<<10)+1],ans,n,m,mapp[105][15],dp[105][(1<<10)+1][(1<<10)+1]; bool check(int r,int x) for(int i=m;i>=1;i--) if(!mapp[r][i]&&(x&1))return false; x>>=1; return true; //检查状态是否合法 int getnum(int r,int x) int res=0; while(x)res+=x&1,x>>=1; return bj[r][num[r][0]]=res; //初始化bj数组 signed main() scanf("%lld%lld",&n,&m); char ch; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>ch; if(ch==‘P‘)mapp[i][j]=1; else mapp[i][j]=0; int maxn=(1<<m)-1; for(int i=1;i<=n;i++) for(int j=0;j<=maxn;j++) if(check(i,j)&&!(j&(j<<1))&&!(j&(j<<2))) num[i][++num[i][0]]=j;//num[i][j]表示第i行编号为j的状态是什么,num[i][0]表示这一行有多少个合法状态 if(i==1)dp[i][num[i][0]][0]=getnum(i,j); bj[i][num[i][0]]=getnum(i,j); for(int i=1;i<=num[2][0];i++) for(int j=1;j<=num[1][0];j++) int x=num[2][i],y=num[1][j]; if(x&y)continue; dp[2][i][j]=max(dp[2][i][j],bj[2][i]+bj[1][j]); //枚举上下两行,初始化dp[2] for(int i=3;i<=n;i++) for(int j=1;j<=num[i][0];j++) for(int k=1;k<=num[i-1][0];k++) for(int l=1;l<=num[i-2][0];l++) int x=num[i][j],y=num[i-1][k],z=num[i-2][l]; if((x&y)||(y&z)||(x&z))continue; dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+bj[i][j]); //枚举这一行、上一行、上上行 for(int i=1;i<=num[n][0];i++) for(int j=1;j<=num[n-1][0];j++) int x=num[n][i],y=num[n-1][j]; if(x&y)continue; ans=max(ans,dp[n][i][j]); //枚举这一行和上一行的可能 printf("%lld",ans); return 0;
以上是关于2019.9.1 炮兵阵地的主要内容,如果未能解决你的问题,请参考以下文章