题目大意:

炮兵阵地 设置炮兵的位置 其上两位 下两位 左两位 右两位 不能同时设置炮兵

 

这题是 corn fields玉米地 的升级版 可以先看下这题的注释 更详细些

第一种方法是网上大多数题解的解法 https://blog.csdn.net/zwj1452267376/article/details/51387718

 

第二种方法是在第一种的基础上

预处理出每一行的可能状态,并直接保存其对应的下标 i , 这样可以通过下标 i ,

直接找到对应的状态 may[i] 和该状态对应的1的个数 num[i] ,而不需要另外将行数与状态及个数对应存储

 

将其建成邻接表的形式

这样在枚举每一行的状态时 只要查询邻接表就行

不需要枚举每种状态再去判断其是否能够对应该行的映像

而找到该行邻接表中存放的状态下标 直接得到该状态及个数

 

预处理出第一行的dp[][][],再依据第一行处理出第二行的dp[][][]

这样在处理之后的各行时 就可以直接判断该行的前两行的状态了

 

/// 第一种方法
#include <bits/stdc++.h>
using namespace std;
int n,m,may[65],num[65];
int mir[105],dp[105][65][65];
int getnum(int w)
{ // 计算w中1的个数
    int cnt=0;
    while(w) {
        cnt+=(w & 1);
        w >>= 1;
    }
    return cnt;
}
int main()
{
    while(~scanf("%d%d",&n,&m)) {
        int len=0;
        for(int i=0;i<(1<<m);i++) // 预处理m列所有可能状态及其1的个数
            if((i&(i<<1))==0 && (i&(i<<2))==0 && ((i<<1)&(i<<2))==0))
                may[len]=i,num[len++]=getnum(i);
        //for(int i=0;i<len;i++) printf("%d %d\n",may[i],num[i]);
        memset(mir,0,sizeof(mir));
        for(int i=0;i<n;i++) {
            char c[15]; scanf("%s",c);
            for(int j=0;j<m;j++)
                if(c[j]=='H') mir[i]|=1<<j; // 处理出每一行的映像 利于寻找可能状态
        }
        memset(dp,0,sizeof(dp));
        for(int i=0;i<len;i++) // 预处理第一行
            if((mir[0]&may[i])==0)
                dp[0][i][0]=max(dp[0][i][0],num[i]);
        for(int i=0;i<len;i++) // 预处理第二行
            if((mir[1]&may[i])==0)
                for(int j=0;j<len;j++)
                    if((may[j]&mir[0])==0 && (may[j]&may[i])==0)
                        dp[1][i][j]=max(dp[1][i][j],dp[0][j][0]+num[i]);
        for(int i=2;i<n;i++) {  // 枚举更新的行数
            for(int j=0;j<len;j++) { // 枚举i行的可能状态
                if((may[j]&mir[i])==0) {
                    for(int k=0;k<len;k++) { // 枚举i-1行的可能状态
                        if((may[k]&mir[i-1])==0 && (may[j]&may[k])==0) {
                            for(int p=0;p<len;p++) { // 枚举i-2行的可能状态
                            if((may[p]&mir[i-2])==0 && (may[p]&may[k])==0 && (may[j]&may[p])==0) 
                                { dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][p]+num[j]); }
                            }
                        }
                    }
                }
            }
        }
        int ans=0;
        for(int i=0;i<len;i++)
            for(int j=0;j<len;j++)
                ans=max(ans,dp[n-1][i][j]);
        printf("%d\n",ans);
    }
    return 0;
}
View Code

相关文章:

  • 2021-09-26
  • 2021-08-03
  • 2021-06-19
  • 2022-01-04
  • 2021-12-31
  • 2022-02-11
  • 2022-01-22
  • 2022-01-15
猜你喜欢
  • 2021-08-12
  • 2021-05-20
  • 2021-12-11
  • 2022-02-04
  • 2022-12-23
  • 2022-12-23
  • 2021-06-18
相关资源
相似解决方案