bzoj1087: [SCOI2005]互不侵犯King
裸的状压dp。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long #define REP(i,s,t) for(int i=s;i<=t;i++) int n,m,state[1000],num[1000]; ll dp[15][1<<11][100]; bool check(int x,int y){ if((x&(y<<1))||(x&(y>>1))||(x&y)) return false; return true; } bool pd(int x){ if((x&(x<<1))||(x&(x>>1))) return false; return true; } int get(int x){ int ans=0; while(x) { if(x&1) ans++;x>>=1; } return ans; } void init(){ scanf("%d%d",&n,&m); REP(i,0,(1<<n)-1) if(pd(i)) state[++state[0]]=i,num[state[0]]=get(i); //rep(i,state[0]) printf("%d %d\n",state[i],num[i]); } void work(){ clr(dp,0); rep(i,state[0]) dp[1][i][num[i]]=1; REP(i,2,n){ rep(j,state[0]) REP(k,0,m) if(dp[i-1][j][k]) rep(t,state[0]) if(check(state[j],state[t])&&k+num[t]<=m) dp[i][t][k+num[t]]+=dp[i-1][j][k]; } ll ans=0; rep(i,state[0]) ans+=dp[n][i][m]; printf("%lld\n",ans); } int main(){ init();work();return 0; }
1087: [SCOI2005]互不侵犯King
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2779 Solved: 1638
[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