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;