bzoj 1087 [SCOI2005]互不侵犯King 状态压缩dp
1087: [SCOI2005]互不侵犯King
Time Limit: 10 Sec Memory Limit: 162 MB[Submit][Status][Discuss]
Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
3 2
Sample Output
16
思路:状态压缩入门题;
#include<bits/stdc++.h> using namespace std; #define ll long long #define esp 1e-13 const int N=5e2+30,M=1e6+50000,inf=1e9+10,mod=1000000007; ll dp[10][N][90]; int check(int t) { int num=t&(t<<1); if(num==0) return 1; return 0; } int check2(int i,int t) { if((i&t)==0&&(i&(t>>1))==0&&(i&(t<<1))==0) return 1; return 0; } int get1(int t) { int sum=0; while(t) { if(t&1) sum++; t>>=1; } return sum; } int main() { int x,y,i,z,t; scanf("%d%d",&x,&y); dp[0][0][0]=1; int u=1; for(i=0;i<x;i++) u*=2; for(i=1;i<=x;i++) { for(t=0;t<u;t++) { if(!check(t)) continue; for(int j=0;j<u;j++) { if(!check(j)) continue; if(!check2(j,t)) continue; int hh=get1(t); for(int k=0;k+hh<=y;k++) dp[i][t][k+hh]+=dp[i-1][j][k]; } } } ll ans=0; for(i=0;i<u;i++) ans+=dp[x][i][y]; printf("%lld\n",ans); return 0; }