E27 状态压缩DP 炮兵部队

视频链接:https://www.bilibili.com/video/BV1vy4y1z7qy/

Luogu P2704 [NOI2001] 炮兵阵地

#include <iostream>
#include <cstring>
#include <algorithm>
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 <iostream>
#include <cstring>
#include <algorithm>
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;
}

 

posted @ 2023-04-10 10:13  董晓  阅读(511)  评论(0编辑  收藏  举报