【题解】[SCOI2005] 互不侵犯 (状压DP)
[SCOI2005] 互不侵犯
终于懂一点状压DP了…
用一个数的二进制形式表示一整行的状态,
比如 18(1010)表示第一列和第三列有国王。
然后用&判断是否可行:
if((x&y)||((x<<1)&y)||(x&(y<<1))) continue;
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 #define FOR(i,n,m) for(register int i=n;i<=m;++i) 7 using namespace std; 8 int n,m,tot; 9 ll ans; 10 int can[1<<10],num[1<<10]; 11 ll dp[10][1<<10][110];//dp[i][j][k]表示第i行,状态为j,前面摆了k个国王时 的方案数 12 int sum(int x)//这一种状态有多少个国王(一行) 13 { 14 while(x) num[tot]+=(x&1),x>>=1; 15 return num[tot]; 16 } 17 int main() 18 { 19 scanf("%d%d",&n,&m); 20 int Max=(1<<n)-1; 21 FOR(i,0,Max) if(!(i&(i<<1))) can[++tot]=i,dp[1][tot][sum(i)]=1; 22 FOR(i,2,n) 23 { 24 FOR(j,1,tot) FOR(k,1,tot) 25 { 26 int x=can[j],y=can[k]; 27 if((x&y)||((x<<1)&y)||(x&(y<<1))) continue;//判断是否可行 28 FOR(l,0,m) dp[i][j][num[j]+l]+=dp[i-1][k][l]; 29 } 30 } 31 FOR(i,1,tot) ans+=dp[n][i][m]; 32 printf("%lld",ans); 33 return 0; 34 }
---------------------
作者:#shadow#
来源:CSDN
原文:https://blog.csdn.net/weixin_44663556/article/details/88378924
版权声明:本文为博主原创文章,转载请附上博文链接!

浙公网安备 33010602011771号