1. 程式人生 > >P1896 [SCOI2005]互不侵犯 狀壓dp

P1896 [SCOI2005]互不侵犯 狀壓dp

bit 加強 using 格子 pac radius 題目 emp 向上

  

題目描述

在N×N的棋盤裏面放K個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各一個格子,共8個格子。

註:數據有加強(2018/4/25)

輸入輸出格式

輸入格式:

只有一行,包含兩個數N,K ( 1 <=N <=9, 0 <= K <= N * N)

輸出格式:

所得的方案數

輸入輸出樣例

輸入樣例#1: 復制
3 2
輸出樣例#1: 復制
16


非常好的狀壓dp
註意預處理完就很好做
技術分享圖片
#include<bits/stdc++.h>
using
namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define
ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 const int N=900; ll dp[10][50000][500]; int cnt,king[N],state[N]; int n,K; void init() { rep(i,
0,(1<<n)-1) if( !(i&(i<<1)) ) { state[++cnt]=i; int temp=i; while(temp) { king[cnt]+=temp&1; temp>>=1; } } } int main() { RII(n,K); init(); rep(i,1,cnt) if(king[i]<=K) dp[1][i][king[i]]=1; rep(i,2,n) rep(j,1,cnt) rep(p,1,cnt) { if(state[j]&state[p])continue; if( (state[j]<<1)&state[p] )continue; if( state[j]&(state[p]<<1))continue; rep(s,king[j],K) dp[i][j][s]+=dp[i-1][p][s-king[j]]; } ll ans=0; rep(j,1,cnt) ans+=dp[n][j][K]; cout<<ans; return 0; }
View Code








P1896 [SCOI2005]互不侵犯 狀壓dp