1. 程式人生 > >C++——狀壓DP模板——互不侵犯【四川省選2005】

C++——狀壓DP模板——互不侵犯【四川省選2005】

互不侵犯【四川省選2005】

題目背景

SCOI2005 DAY2 T3

題目描述

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

輸入格式

輸入只有一行,包含兩個數 N,K(1≤N≤9,0≤K≤N*N)。

輸出格式

輸出方案數。

樣例資料 1

輸入  [複製]

3 2

輸出

16
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=10,M=26,P=512;
int n,m,t,g[P];
long long ans,f[N][P][M];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cin>>n>>m;
	if(m>25||m>=n*n) cout<<"0"<<endl;
	else
	{
		t=1<<n;
		f[0][0][0]=1;
		g[0]=0;
		for(int i=1;i<t;++i) g[i]=g[i>>1]+(i&1);
		for(int i=1;i<=n;++i)
			for(int j=0;j<t;++j)
				if(g[j]<=m&&!(j&j>>1))
					for(int k=0;k<t;++k)
						if(g[k]<=m&&!(k&k>>1)&&!(k&j)&&!(j&k>>1)&&!(j&k<<1))
							for(int l=g[j]+g[k];l<=m;++l)
								f[i][j][l]+=f[i-1][k][l-g[j]];
		for(int i=0;i<t;++i)
			ans+=f[n][i][m];
		cout<<ans<<endl;
	}
	return 0;
}