E27 状态压缩DP 炮兵部队_哔哩哔哩_bilibili
P2704 [NOI2001] 炮兵阵地 - 洛谷
#include<bits/stdc++.h>
using namespace std;
const int N=110, M=1<<10;
int n,m; //行数,列数
int g[N]; //存储地图各行数值
int cnt; //一行的合法状态个数
int s[M]; //一行的合法状态集
int num[M]; //每个合法状态包含1的个数
int f[N][M][M]; //110*1024*1024*4 = 440MB
// f[i][a][b]表示已放好前i行,
// 第i行第a个状态,第i-1行第b个状态时,能放置的最大数量
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=0;j<m;j++){
char c; cin>>c;
if(c=='P') g[i]+=1<<(m-j-1); //地图各行数值
}
for(int i=0; i<(1<<m); i++) //枚举一行的所有状态
if(!(i&i>>1) && !(i&i>>2)){ //如果不存在11和101
s[cnt++]=i; //保存一行的合法状态
for(int j=0; j<m; j++)
num[i]+=(i>>j&1); //每个合法状态包含1的个数
}
for(int i=1; i<=n+2; i++) //枚举行
for(int a=0; a<cnt; a++) //枚举第i行合法状态
for(int b=0; b<cnt; b++) //枚举第i-1行合法状态
for(int c=0; c<cnt; c++) //枚举第i-2行合法状态
if(!(s[a]&s[b])&&!(s[a]&s[c])&&!(s[b]&s[c])
&&(g[i]&s[a])==s[a]&&(g[i-1]&s[b])==s[b])
f[i][a][b]=max(f[i][a][b],f[i-1][b][c]+num[s[a]]);
cout<<f[n+2][0][0]<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=110, M=1<<10;
int n,m; //行数,列数
int g[N]; //存储地图各行数值
int cnt; //一行的合法状态个数
int s[M]; //一行的合法状态集
int num[M]; //每个合法状态包含1的个数
int f[2][M][M]; //滚动数组 2*1024*1024*4 = 8MB
// f[i][a][b]表示已放好前i行,
// 第i行第a个状态,第i-1行第b个状态时,能放置的最大数量
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=0;j<m;j++){
char c; cin>>c;
if(c=='P') g[i]+=1<<(m-j-1); //地图各行数值
}
for(int i=0; i<(1<<m); i++) //枚举一行的所有状态
if(!(i&i>>1) && !(i&i>>2)){ //如果不存在11和101
s[cnt++]=i; //保存一行的合法状态
for(int j=0; j<m; j++)
num[i]+=(i>>j&1); //每个合法状态包含1的个数
}
for(int i=1; i<=n+2; i++) //枚举行
for(int a=0; a<cnt; a++) //枚举第i行合法状态
for(int b=0; b<cnt; b++) //枚举第i-1行合法状态
for(int c=0; c<cnt; c++) //枚举第i-2行合法状态
if(!(s[a]&s[b])&&!(s[a]&s[c])&&!(s[b]&s[c])
&&(g[i]&s[a])==s[a]&&(g[i-1]&s[b])==s[b])
f[i&1][a][b]=max(f[i&1][a][b],f[i-1&1][b][c]+num[s[a]]);
cout<<f[n+2&1][0][0]<<endl;
return 0;
}