状态压缩DP

/*
炮兵阵地
*/

const
int N=200; int no[N],can[100+10],num[100+10],n,m; int f[N][1000][1000];//10^8 char s[20];int maxn,cnt; inline int lowbit(int x) { return x&(-x); } int main() { //freopen("exam.txt","r",stdin); n=re(),m=re(); maxn=(1<<m)-1; //chu("%d %d %d\n",m,(1<<m)-1,maxn); _f(i,1,n) { scanf("%s",s); _f(j,0,m-1) { if(s[j]=='H') { no[i]+=(1<<j); } } } //chu("max:%d\n",maxn); _f(i,0,maxn) { if(!((i<<2)&i)) { if(!((i<<1)&i)) { can[++cnt]=i; for(int o=i;o;o-=lowbit(o))++num[cnt]; } } } //chu("cnt:%d\n",cnt); _f(x,0,n) { _f(i,1,cnt) { _f(j,1,cnt) { f[x][can[i]][can[j]]=-inf; //chu("change:%d %d %d\n",x,can[i],can[j]); } } } f[0][0][0]=0; // return 0; _f(x,1,n) { _f(i,1,cnt) { int ii=can[i]; if(ii&no[x])continue; _f(j,1,cnt) { int jj=can[j]; if(jj&no[x-1])continue; if(ii&jj)continue; _f(k,1,cnt) { int kk=can[k]; if(kk&ii)continue; //if(no[x-2]&kk)continue; f[x][ii][jj]=max(f[x-1][jj][kk]+num[i],f[x][ii][jj]); // chu("f[%d %d %d]:%d\n",x,ii,jj,f[x][ii][jj]); } } } } int ans=0; _f(i,1,cnt) { _f(j,1,cnt) { ans=max(ans,f[n][can[i]][can[j]]); } } chu("%d",ans); return 0; } /*
这里要注意,状态压缩一般需要初始化,f[0][0]=1或者0,具体要看意义
如果是可能性,则为1,最值是0
还有几个位运算基本操作,比如二进制1的个数,二进制数空几个是0
及其注意:三维数组memset超级慢!!!千万别用
*/
/*
特殊棋盘方格
非常整体思维的一道状压
*/
const
int N=20; inline int lowbit(int x) { return (x)&(-x); } ll f[(1<<N)+10];ll no[N+10]; int n,m; int main() { //freopen("exam.txt","r",stdin); n=re(),m=re(); _f(i,1,m) { int x=re(),y=re(); no[x]+=(1<<(y-1)); } f[0]=1; ll can=(1<<(n))-1; // chu("%lld\n",can); _f(i,1,can) { int cnt=0; for(int k=i;k;k-=lowbit(k))cnt++; for(int k=i;k;k-=lowbit(k)) { int j=lowbit(k);//在cnt行j状态列放棋子 if(j&no[cnt])continue; //那其他列就要放其他棋子 int jj=j^i;//j放了其他就不用放了 f[i]+=f[jj]; // chu("f[%d]:%lld\n",i,f[i]); } } chu("%lld",f[can]); return 0; } /* f[j]表示到j状态的方案数 no[i]=j不合法地形 for(1-(1<<n)-1)循环状态 for(j:1-i)cnt统计这个状态1的个数,就是统计到了第几行 int n,m;scanf("%d%d",&n,&m); for(int i = 1;i <= m;i++){ int x,y;scanf("%d%d",&x,&y); a[x] += 1<<(y-1); } f[0] = 1; int maxs = 1<<n; for(int s = 1;s < maxs;s++){ int cnt = 0; for(int i = s;i;i-=lowbit(i))cnt++; for(int i = s;i;i-=lowbit(i)){ if(!(a[cnt] & lowbit(i))){ int ss = s^lowbit(i); f[s] += f[ss]; } } } printf("%lld\n",f[maxs - 1]); return 0; */

 

posted on 2022-04-09 15:06  HZOI-曹蓉  阅读(21)  评论(0)    收藏  举报