洛谷 P2051 AHOI2009 中國象棋

2021-07-23 19:29:31 字數 1537 閱讀 4615

題目描述

這次小可可想解決的難題和中國象棋有關,在乙個n行m列的棋盤上,讓你放若干個炮(可以是0個),使得沒有乙個炮可以攻擊到另乙個炮,請問有多少種放置方法。大家肯定很清楚,在中國象棋中炮的行走方式是:乙個炮攻擊到另乙個炮,當且僅當它們在同一行或同一列中,且它們之間恰好 有乙個棋子。你也來和小可可一起鍛鍊一下思維吧!

輸入輸出格式

輸入格式:

一行包含兩個整數n,m,之間由乙個空格隔開。

輸出格式:

總共的方案數,由於該值可能很大,只需給出方案數模9999973的結果。

輸入輸出樣例

輸入樣例#1:

1 3

輸出樣例#1:

7 說明

樣例說明

除了3個格仔裡都塞滿了炮以外,其它方案都是可行的,所以一共有2*2*2-1=7種方案。

資料範圍

100%的資料中n和m均不超過100

50%的資料中n和m至少有乙個數不超過8

30%的資料中n和m均不超過6

【分析】

特別神奇的狀態轉移

唉又是一道省選dp神題 還帶組合數= =

我手玩幾組資料之後發現行列貌似可以交換的

然後還是不會做 只好求助於各神犇 題解比較少= =湊個熱鬧

dp[i][j][k]表示在前i行中有j列已經有2個 有k列已經有1個 那麼0的個數就是m-j-k個

轉移方程看**

這一行可以不放

那麼直接加上dp[i-1][j][k]

放乙個的話

可以把一列0變成1

可以把一列1變成2

放兩個的話

可以把兩列0變成1

可以把兩列1變成2

還有 可以把一列0變成1 再把另外一列1變成2

關於組合數要說一下。。

放乙個好說 直接乘1或0的個數完事(加在任意乙個上面都是可以的)

放兩個的話 前兩個也好弄 直接c(n,2) (n為可選個數)

最後乙個呢 先乘上原來0的個數 再乘上原來1的個數 乘法原理嘛= =

【**】

//p2051 [ahoi2009]中國象棋

#include

#include

#include

#include

#include

#define ll long long

#define m(a) memset(a,0,sizeof a)

#define fo(i,j,k) for(i=j;i<=k;i++)

using

namespace

std;

const

int mod=9999973;

ll f[105][105][105];

int n,m,ans;

int main()

fo(j,0,m)

fo(k,0,m-j)

ans=(ans+f[n][j][k])%mod;

printf("%d\n",ans);

return

0;}

洛谷 P2051 AHOI2009 中國象棋

這道題主要是狀態很難想到 首先可以看出每行每列不能超過2個棋子 也就是說有0,1,2三種狀態 所以可以一行一行來處理 那就用放了0個棋子的列數是 那麼這個時候狀態轉移方程就非常好寫了。對於當前這一行可以不放,放乙個,放兩個棋子 表示沒有棋子的列,1表示有1個棋子的列。那麼有幾種情況 不放放乙個在 放...

洛谷 P2051 AHOI2009 中國象棋

題目 中國象棋 思路 首先是30分暴力 直接dfs就好。用row和col儲存狀態。include using namespace std define maxn 100 define read x scanf d x define md 9999973 int n,m int rw maxn 5 c...

洛谷 P2051 AHOI2009 中國象棋

這次小可可想解決的難題和中國象棋有關,在乙個n行m列的棋盤上,讓你放若干個炮 可以是0個 使得沒有乙個炮可以攻擊到另乙個炮,請問有多少種放置方法。大家肯定很清楚,在中國象棋中炮的行走方式是 乙個炮攻擊到另乙個炮,當且僅當它們在同一行或同一列中,且它們之間恰好 有乙個棋子。你也來和小可可一起鍛鍊一下思...