裸的状压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
",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
",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