P2051 AHOI2009 中國象棋

2022-04-10 04:41:08 字數 1597 閱讀 7594

這次小可可想解決的難題和中國象棋有關,在乙個 n 行 m 列的棋盤上,讓你放若干個炮(可以是 0個),使得沒有乙個炮可以攻擊到另乙個炮,

且它們之間恰好 有乙個棋子。你也來和小可可一起鍛鍊一下思維吧!

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

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

輸入 #1

1 3輸出 #1

樣例說明

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

對於 30%的資料,n 和 m 均不超過 6。

對於 50% 的資料,n 和 m 至少有乙個數不超過 8。

對於 100% 的資料,1≤n,m≤100。

對於前30%的資料,我們可以爆搜拿部分暴力分。

然後,我們就需要開始考慮正解。

首先,根據中國象棋的芝士,每行每列只能放兩個炮(這不是廢話嗎)。

我們就可以根據這個列出方程

我們設 f[i][j][k]表示第i行,其中有j列放了乙個棋子,k列放了兩個棋子的方案數。

轉移:考慮第i行的放置情況

不放的情況 這時候我們可以直接由f[i-1][j][k]轉移過來

放乙個的情況,並且放在了之前沒有炮的列上,由於我們在沒有炮的一列放了乙個,會使放乙個炮的列數加1,

這種沒放炮的列一共有\(m-j-k+1\)列,統計一下就行了

放乙個炮,並且放在了之前就有乙個炮的列上,我們在乙個有乙個炮的列上放了乙個,就會導致放兩個炮的列加一.

放乙個炮列的減一,再加上有j-1列可以放。就是 f[i-1][j+1][k-1] * (j+1)

放兩個炮的情況,兩個炮都放在沒有炮的列上,會導致放乙個炮的列加二,並且這樣的列一共有\(m-j-k+2\)

利用組合數算出答案就解決了方程就是 f[i-1][j-2][k] * calc(m-j-k+2,2)

放兩個炮的情況,都放在之前放過兩個炮的列上,會導致放兩個炮的列加二,放乙個炮的列數減二,再加上這樣的列

一共有\(j+2\)列。 方程就可以寫成 f[i-1][j+2][k-2] * calc(j+2,2)

放兩個炮的情況,且乙個放在之前沒有炮的地方,另乙個放在之前有乙個炮的地方,這就會導致放兩個炮的數量加一。

放乙個炮的列數不變(加一後又減一) 再加上有\(j*(k-1)\)中情況,直接計算就okk了

答案就是\(\sum_^ \sum_^f[n][i][j]\)

這題,分類討論確實煩了點,令人想吐

#include#include#includeusing namespace std;

#define ll long long

const int p = 9999973;

int n,m;

ll c[110][110],f[110][110][110],ans;

void yych() }}

ll calc(int n,int m)

int main()

} }for(int i = 0; i <= m; i++) }

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

return 0;

}

P2051 AHOI2009 中國象棋 (dp)

傳送門 n和m太大了,狀壓dp不行。換一種方式 定義f i j k 為前i行中有就 j 列放了乙個,k列放了2個的方案數。總共有m列,什麼也沒放的有 s m j k 列。第 i 行有三種選擇不放,放乙個 放s或j中,k已經放不下了 放兩個 全放s,乙個s乙個j,兩個j 需要注意一直保持 s j k ...

題解 P2051 AHOI2009 中國象棋

題目鏈結 題目大意 求在 n 行 m 列的棋盤上放置若干個炮使得它們互不攻擊的方案數,對 9999973 取模 動態規劃,計數 分析 沒有炮互相攻擊等價於沒有三個炮在同一行 列 考慮用 f i m 1 m 2 表示前 i 行,有 m 1 列有乙個炮,m 2 列有兩個炮的方案數 可以用刷表法降低思維難...

P2051 AHOI2009 中國象棋 DP

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