LOJ #10170. 「一本通 5.4 例 1」騎士
阿新 • • 發佈:2018-12-09
題目描述
在 n×nn \times nn×n 的棋盤上放 kkk 個國王,國王可攻擊相鄰的 888 個格子,求使它們無法互相攻擊的方案總數。
輸入格式
只有一行,包含兩個整數 nnn 和 kkk。
輸出格式
每組資料一行為方案總數,若不能夠放置則輸出 000。
樣例
樣例輸入 1
3 2
樣例輸出 1
16
樣例輸入 2
4 4
樣例輸出 2
79
資料範圍與提示
對於全部資料,1≤n≤10,0≤k≤n21\le n\le 10, 0\le k\le n^21≤n≤10,0≤k≤n2。
這是一道最基礎的狀壓dp
不過陣列一定要開大
每層狀態最高才143種
#include<cstdio> #define ll long long using namespace std; inline int read() { int ret=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') ret=(ret<<1)+(ret<<3)+ch-'0',ch=getchar(); return ret; } int n,m,cnt; const int N=11,S=1100; int a[S],sum[S]; ll f[N][S][105]; int main() { n=read(),m=read(); for(int i=0;i<(1<<n);i++) { if(i&(i<<1)||i&(i>>1))continue; a[++cnt]=i; int x=i; while(x) sum[cnt]+=x&1,x>>=1; } for(int i=1;i<=cnt;i++) f[1][i][sum[i]]=1; for(int i=2;i<=n;i++) for(int j=1;j<=cnt;j++) for(int k=1;k<=cnt;k++) { if(a[j]&a[k]||(a[j]>>1)&a[k]||(a[j]<<1)&a[k]) continue; for(int l=sum[j]+sum[k];l<=m;l++) f[i][j][l]+=f[i-1][k][l-sum[j]]; } ll ans=0; for(int i=1;i<=cnt;i++) ans+=f[n][i][m]; printf("%lld\n",ans); return 0; }