E25 状态压缩DP 小国王

E25 状态压缩DP 小国王_哔哩哔哩_bilibili

 

P1896 [SCOI2005] 互不侵犯 - 洛谷

// 
#include<bits/stdc++.h>
using namespace std; 

int n,k;        //棋盘行数,国王总数
int cnt;        //一行的合法状态个数
int s[1<<12];   //一行的合法状态集
int num[1<<12]; //每个合法状态包含的国王数
long long f[12][144][1<<12];
//f[i,j,a]表示前i行已放了j个国王,第i行的第a个状态时的方案数 

int main(){
  cin>>n>>k;
  for(int i=0; i<(1<<n); i++) //枚举一行的所有状态
    if(!(i & i>>1)){          //如果不存在相邻的1
      s[cnt++]=i;             //一行的合法状态集,例101
      for(int j=0; j<n; j++)
        num[i]+=(i>>j & 1);   //每个合法状态包含的国王数
    }
  
  f[0][0][0]=1;                   //边界
  for(int i=1; i<=n+1; i++)       //枚举行
    for(int j=0; j<=k; j++)       //枚举国王数
      for(int a=0; a<cnt; a++)    //枚举第i行的合法状态
        for(int b=0; b<cnt; b++){ //枚举第i-1行的合法状态
          int c=num[s[a]];        //第i行第a个状态的国王数
          if((j>=c)               //可以继续放国王
            &&!(s[b]&s[a])        //不存在同列的1
            &&!(s[b]&(s[a]<<1))   //不存在斜对角的1
            &&!(s[b]&(s[a]>>1)))
              f[i][j][a]+=f[i-1][j-c][b]; //行间转移
        }
  cout<<f[n+1][k][0]<<endl;       //第n+1行不放国王的方案数
  return 0;
}

 

posted @ 2023-04-10 10:11  董晓  阅读(1450)  评论(0)    收藏  举报