炮兵阵地

    xiaoxiao2025-04-24  10

    三维的dp[i][a][b],表示第i行,前一行状态为a,再前一行的状态为b,用二进制表是状态如10010表示第一和第四个位置有阵地,然后预处理出每一种状态的炮兵数量。

    每一行读取完后就预处理该行所有可能的状态, x&x<<1和x&x<<2 的值为0即本行炮兵不会相互干扰(详见位运算)。

     注意第一行和第二行先进行dp,再处理后面几行。

    #include<cstdio> #include<cstring> #include<algorithm> #define N 10 using namespace std; int z, st[111], s[111][1<<N],//枚举每行所有可能的状态 num[1<<N]//每种状态炮兵数量, dp[111][1<<N][1<<N]; inline int pd(int x){ return x&(x<<1)||x&(x<<2); } inline int pd2(int x, int y){ return x&y; } void turn(){ for(int i=0;i<z;i++){ int x=i, sum=0; while(x){ sum+=x&1; x>>=1; } num[i]=sum; } } int main() { int n, m; char c[20]; scanf("%d %d", &n, &m); z=1<<m; for(int i=1;i<=n;i++){ scanf("%s", c); for(int j=0;j<m;j++){ if(c[j]=='H') st[i]+=(1<<j); } for(int k=0;k<z;k++) if(!pd(k)&&!pd2(k,st[i])) s[i][++s[i][0]]=k; } turn(); for(int i=1;i<=s[1][0];i++) dp[1][s[1][i]][0]=num[s[1][i]]; for(int i=1;i<=s[2][0];i++){ for(int j=1;j<=s[1][0];j++){ if(pd2(s[2][i],s[1][j])) continue; dp[2][s[2][i]][s[1][j]]=max(dp[2][s[2][i]][s[1][j]], dp[1][s[1][j]][0]+num[s[2][i]]); } } for(int i=3;i<=n;i++) for(int a=1;a<=s[i][0];a++){ for(int b=1;b<=s[i-1][0];b++){ if(pd2(s[i][a],s[i-1][b])) continue; for(int c=1;c<=s[i-2][0];c++){ if(pd2(s[i][a],s[i-2][c])) continue; dp[i][s[i][a]][s[i-1][b]]=max(dp[i][s[i][a]][s[i-1][b]], dp[i-1][s[i-1][b]][s[i-2][c]]+num[s[i][a]]); } } } int maxn=0; for(int i=1;i<=s[n][0];i++) for(int j=1;j<=s[n-1][0];j++) maxn=max(maxn,dp[n][s[n][i]][s[n-1][j]]); printf("%d\n", maxn); return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-1298399.html
    最新回复(0)