初见安~好久没写博客了哈哈哈过暑假去了:)
题目描述
这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!
输入格式
一行包含两个整数N,M,之间由一个空格隔开。
输出格式
总共的方案数,由于该值可能很大,只需给出方案数模9999973的结果。
输入
1 3
输出
7
说明/提示
样例说明
除了3个格子里都塞满了炮以外,其它方案都是可行的,所以一共有2*2*2-1=7种方案。
数据范围
100%的数据中N和M均不超过100
50%的数据中N和M至少有一个数不超过8
30%的数据中N和M均不超过6
题解
一看就是要用dp的题。求方案数这种东西不是数论就是dp……
考虑dp的话,如果我们以行为阶段,那么可以直接保证每一行最多两个炮;而后的状态就是在哪里放,我们可以考虑每一列的状态——三种,全空,有一个炮和有两个炮。并且我们只考虑数量不考虑这些列的位置,所以就可以得出状态:设表示到第i行,有j列只有1个炮,有k列有两个炮时的方案数。【这样设置看起来很奇怪……反正我没想到】转移起来,我们就会考虑到6种情况:
一、一个都不放
直接。
二、放一个
1.放在空的列上:,因为多了一列有一个炮的,情况数为空列的数量,作差得到。
2.放在有一个炮的列上:,相当于用一个一列一个的换成了一个一列两个的。
三、放两个
1.都放在空的列上:,道理同二1。因为放两个所以涉及到组合数。
2.一个放在一个一列上,一个放在空列上:。
3.都放在一个一列的上面:
综上就是六种情况……看起来真的很恶心对不对!!!!我有可能有打错了的地方,望周正:)
所以在上面的条件枚举完了过后我们统计一下ans就差不多了。
ans统计哪里?
只要是到了第n行的合法状态都可以。
最后提醒,因为如果一直求组合数的话可能会很麻烦,而且都是取两个,这就很方便了我们直接化简一下组合数的过程:
重点就是这些了。:)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxn 105
using namespace std;
const int mod = 9999973;
typedef long long ll;
int read() {
int x = 0, f = 1, ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
return x * f;
}
int n, m;
ll dp[maxn][maxn][maxn], ans;
int main() {
n = read(), m = read();
dp[0][0][0] = 1;
for(int i = 1; i <= n; i++) {//建议不要看这一大坨,看上面的情况自己写吧。
for(int j = 0; j <= m; j++) {
for(int k = 0; j + k <= m; k++) {
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j][k]) % mod;
if(j > 0) dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j - 1][k] * (m - j - k + 1)) % mod;
if(k > 0) dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j + 1][k - 1] * (j + 1) + dp[i - 1][j][k - 1] * j * (m - j - k + 1)) % mod;
if(j > 1) dp[i][j][k] = (dp[i][j][k] + (dp[i - 1][j - 2][k] * (m - j - k + 2) * (m - j - k + 1) / 2)) % mod;
if(k > 1) dp[i][j][k] = (dp[i][j][k] + (dp[i - 1][j + 2][k - 2] * (j + 2) * (j + 1) / 2)) % mod;
}
}
}
for(int j = 0; j <= m; j++) for(int k = 0; j + k <= m; k++) ans += dp[n][j][k], ans %= mod;
printf("%lld\n", ans);
return 0;
}
有史以来注释最少的一次题解哈哈哈哈哈……
迎评:)
——End——