histcat

histcat

P1896 [SCOI2005] 互不侵犯

題目#

[SCOI2005] 互不侵犯#

題目描述#

在 $N \times N$ 的棋盤裡面放 $K$ 個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各一格,共 $8$ 個格子。
對於全部數據,$1 \le N \le 9$,$0 \le K \le N\times N$。

題解#

f[i][j][k]表示推到了第 i 行,到目前為止選了 j 個國王,第 i 行的狀態為 k 的方案數

然後枚舉i,j,k以及前一行的狀態轉移即可

問題#

1. 不開long long見祖宗

2. 第二位要開N * N

代碼#

#include<bits/stdc++.h>
#define int long long
using namespace std;

int read()
{
	int f = 1, x = 0;
	char ch = getchar();
	while(ch < '0' || ch > '9')
	{
		if(ch == '-') f = -1;
		ch = getchar();
	}

	while(ch >= '0' && ch <= '9')
	{
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return f * x;
}
const int N = 10;
int f[N][N * N][1 << 9];
int sum[1 << 9];
int n, k;

int getsum(int x)
{
	int ans = 0;
	while(x)
	{
		x &= (x - 1);
		ans++;
	}
	return ans;
}

signed main()
{
	for(int i = 0;i < (1 << 9);i++)
	{
		sum[i] = getsum(i);
	}
	n = read(), k = read();
	for(int s = 0;s < (1 << n);s++)
	{
		f[1][sum[s]][s] = 1;
	}

	for(int i = 2;i <= n;i++)
	{
		for(int j = 0;j <= k;j++)
		{
			for(int s = 0;s < (1 << n);s++)
			{
				if((s >> 1) & s || (s << 1) & s || sum[s] > j) continue;
				for(int fl = 0;fl < (1 << n);fl++)
				{
					if((fl >> 1) & fl || (fl << 1) & fl || (fl << 1) & s || fl & s || (fl >> 1) & s || sum[fl] + sum[s] > j) continue;
					f[i][j][s] += f[i - 1][j - sum[s]][fl];
				}
			}
		}

	}

	long long ans = 0;
	for(int s = 0; s < (1 << n);s++)
	{
		if((s >> 1) & s) continue;
			ans += f[n][k][s];
	}
	cout << ans;
	return 0;
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。