P1896 [SCOI2005] Non-aggression (like pressure dp)

Topic connection

Question: How many placement schemes are there to place K kings on the N×N chessboard so that they do not attack each other? The king can attack it up, down, left, and right, and one grid in each of the eight directions from top left, bottom left, top right, and bottom right, for a total of 8 grids.

Idea: Let dp[ i ][ j ][ k] be the number of plans where the state of the kings placed on the i-th row is j and the number of kings on the chessboard is k, then the state of the first row is processed first, and the transformation related to the matrix The basic dp routine is to process the first line, then enumerate the following lines, enumerate the state of the previous line of the current line, enumerate the state of the current line, exclude the state that does not meet the conditions, and transfer it. Note that the last The answer is the sum of dp[ i ][ j ][ K] and j! =0, because when j is equal to 0, some states are calculated repeatedly.

#include <bits/stdc++.h>
#define pi pair<int,int>
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 12;
int dp[maxn][1<<maxn][maxn*maxn];
int n,D;
int count(int s)
{
	int ans = 0;
	for(int i=0;i<n;i++)if((1<<i&s)!=0)++ans;
	return ans;
}
int main()
{
	scanf("%d%d",&n,&D);
	for(int i=0;i<1<<n;i++)
	if((i<<1&i)==0 && (i>>1&i)==0)dp[1][i][count(i)] = 1;
	for(int i=2;i<=n;i++)
	for(int s=0;s<1<<n;s++)
	for(int s0=0;s0<1<<n;s0++)
	{
		int c = count(s0);
		if((s0>>1&s0)==0 && (s0<<1&s0)==0 && (s0<<1&s)==0 && (s0&s)==0 && (s0>>1&s)==0)
		for(int k=0;c+k<=D;k++)
		{
			if(dp[i-1][s][k]==0)continue;
			dp[i][s0][c+k] += dp[i-1][s][k];
		}
	}
	ll ans = 0;
	for(int i=1;i<=n;i++)
	for(int j=1;j<1<<n;j++)ans += dp[i][j][D];
	cout<<ans<<'\n';
}

 

Guess you like

Origin blog.csdn.net/weixin_44499508/article/details/105410873