洛谷 P2051 AHOI2009 中國象棋

2022-02-27 13:31:37 字數 1768 閱讀 6405

這次小可可想解決的難題和中國象棋有關,在乙個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

留給讀者一點思考時間吧!

接下來,我來講講我怎麼想的吧!

首先,做題之前,我們要冷靜,不要看到省選題就 想ac 怕!

留心觀察數巨範圍,我們發現,這大概是標準的2-3維的動態規劃題的資料規模。

既然這麼想,那麼我們肯定先考慮高維的狀態設計了。

我是這麼設計的:

首先它有n行m列,而兩個炮又不能在一列,所以這麼定義$f[i][j][k]$.

i表示已經放了i行棋子,作為第一維來列舉。

j表示在m列裡,有j列只有乙個炮。

最後,k表示有k列有兩個炮。那麼狀態設計好了,怎麼轉移呢?

肯定的,我們先來列舉i行。

在這i行裡,我們下棋的方案數:

1.首先肯定先要繼承上一行列舉完的所有方案數,所以$$f[i][j][k]=f[i-1][j][k]$$

2.從最簡單的下起,我們先一行只下乙個吧,那麼先找到空的行,沒有棋子,我們可以隨便怎麼下。

那麼有:$$f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1)$$

3.還有,我們還可以把這乙個炮下在只有乙個炮的那一列,那麼:$$f[i][j][k]+=f[i-1][j+1][k-1]*(j+1)$$

4.同時,列舉新的一行時,我們可以在這一行下兩個棋子。

還是從最簡單的開始,我們下在沒有炮的那兩列:$$f[i][j][k]+=f[i-1][j-2][k]*c(m-j-k+2,2)$$

5.我們還可以下在兩個原來都有乙個炮的那兩列:$$f[i][j][k]+=f[i-1][j+2][k-2]*c(j+2)$$

6.最後,其實還有一種下法,我們可以將乙個炮下在沒有炮的那一列,另乙個下在有炮的一列。

那麼有:$$f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1)$$

p.s. 為了不讓陣列越界,我們要加一些判斷,如$if (j>=1)$之類的。

**在下面啦

#include #define c(x) ((x)*(x-1)/2)

using

namespace

std;

intmain()

; cin>>n>>m;

for (int i=1;i<=n;i++)

for (int j=0;j<=m;j++)

for (int k=0;k+j<=m;k++)

for (int j=0;j<=m;j++)

for (int k=0;k+j<=m;k++)

ans+=f[n][j][k],ans%=mo;

cout

return0;

}

洛谷 P2051 AHOI2009 中國象棋

題目描述 這次小可可想解決的難題和中國象棋有關,在乙個n行m列的棋盤上,讓你放若干個炮 可以是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...