这题碉堡了。
给一个N*N的棋盘,让你放皇后。
要求:
1、每行有且只有2个Queen;
2、每列有且只有2个Queen;
规定:
如果两个棋盘,经过行交换和列交换,可以互相转换,那这两个局面等价。
目标:
给N,求出可以有多少种摆法(局面)。
分析:
这个题目,乍一看真的很无从下手。但是看到提示那个“规定”,这个等价提示了什么呢?
在“行交换”和“列交换”的过程里, 什么 是不变的?
既然行和列的排列是自由的,那他们之间联系起来的纽带是什么呢?
你会发现(其实是神明发现的。。。),是那些在同一条线上的Queen们。
两个行,比如 x 和 y ,他们如果有在同一线上的Queen,那么我们就把这2个行,分在同一组,这里简称 x和y “相关” 。
那么假设有 a 个行 通过 “相关” 分在了同一组,我们就可以说,这是一个 有 a 个元素的组。
那么一共有多少行呢? n 行。
是不是明白了?
题目转化为——求把n分解成 不小于2 的整数 ,的分配方案数。
跟上一题《Housing》是一样的!完全背包。(详见上一篇)
dp[i][j] 表示 --- 把 i 分解成 不小于 j 的整数和 , 有多少种方案。
代码:
#include <cstdio>
using namespace std ;
#define maxn 509
#define max(a,b) a>b?a:b
int t,n;
int dp[maxn][maxn] ;
void DP_run () {
dp[2][2] = 1 ;
for ( int i = 0 ; i <= 500 ; ++i ) {
dp[i][i] = dp[i][i-1] = 1 ; // i itself
for ( int j = 0 ; j <= 500 ; ++j ) {
if ( i == 0 ) dp[i][j] = 1 ;
else if ( i < j ) dp[i][j] = 0 ;
else {
dp[i][j] = 0 ;
for ( int k = max(2,j) ; k <= i ; ++k ) {
dp[i][j] = (dp[i][j]+dp[i-k][k])%1000007 ;
}
}
}
}
}
int main () {
scanf ( "%d" , &t ) ;
DP_run() ;
while ( t-- ) {
scanf ( "%d" , &n ) ;
printf ( "%d\n" , dp[n][2] ) ;
}
//system ( "pause" ) ;
return 0 ;
}
585

被折叠的 条评论
为什么被折叠?



