P2704 感觉思路错了

P2704 [NOI2001] 炮兵阵地

phmaprostrate @ 2021-08-20 21:33:41

没用滚动数组 因为样例没过 思路是 预处理 2行。然后枚举前两行。

#include<iostream>
using namespace std;
const int N = 102,M = 11,S = 1 << M;
int s[N][M];
int so[S];
int Map[N];
bool can[S];
bool check(int ss){
    if(((ss << 1) & ss) == 0 &&((ss << 2) & ss) == 0) return true;
    else return false;
}
int n,m;
int dp[N][S][S];
int main(){
    cin >> n >>m;
    for(int i = 1;i <= n;i++)
     for(int j = 1;j <= m;j++){
        char x; 
        cin >> x;
        s[i][j] = (x == 'P');
        Map[i] = (Map[i] << 1) + (x == 'P');
     }
     int statem = 1 << m - 1;
     for(int i = 0;i <= statem;i++){
        int x = i;//处理每个状态的炮兵
        while(x){
        so[i]++;
         x = (x - 1) & x;   
         }
     }
     for(int i = 0;i <= statem;i++){
        if(check(i)) can[i] = true;
     }
     //第一行
     for(int i = 0;i <= statem;i++){
        if(can[i] && ((Map[1] & i) == i)) dp[1][0][i] = so[i];
     }
     // 第2行
     for(int i = 0;i <= statem;i++){
        if(can[i] && ((Map[1] & i) == i)){
            for(int j = 0;j <= statem;j++){
                if(!can[j] || (i & j) || ((Map[2] & j)!=j)) continue;
                dp[2][i][j] = dp[1][0][i] + so[j];
             }
         }
     }
     for(int i = 3;i <= n;i++)
      for(int j = 0;j <= statem;j++){
        if(can[j] && ((Map[j] & j) == j)){
            for(int s = 0;s <= statem;s++){
                if(!can[s] ||(s & j) || ((Map[i - 1] & s) != s)) continue;
                for(int u = 0;u <= statem;u++){
                    if(!can[u] || (u & s) || ((Map[i - 2] & u) != u)) continue;
                    dp[i][s][j] = max(dp[i][s][j],dp[i - 1][u][s] + so[j]);
                  }
              }
          }
      }
      int ans = 0;
      for(int u = 0;u <= statem;u++)
       for(int j = 0;j <= statem;j++){
        ans = max(ans,dp[n][u][j]);
       }
       cout<<ans;
    return 0;
}

by w23c3c3 @ 2021-08-20 21:45:56

没仔细看
int statem = (1 << m) - 1;


|