洛谷P2051 AHOI2009 中國象棋

2022-03-17 15:02:57 字數 1309 閱讀 2253

題目

運用數學知識遞推。定義\(dp[i][j][k]\)為前i行內選擇j個列只有乙個炮,k列只有兩個炮的放置方案總數。

因為如果有一列或者一行的炮大於等於三時,必會有乙個炮會被攻擊到,所以可以用乙個和兩個來區分,方便遞推。這樣可以使的列裡面的炮不會大於等於三,然後考慮行,這一行內只能放兩個或乙個,所以可以考慮從這方面來推出遞推公式。放的這乙個或兩個炮會改變列上的炮數,所以可以從上一行的炮的狀態轉移。

有遞推公式:

dp[i][j][k] = (dp[i][j][k] + (j + 1) * dp[i - 1][j + 1][k - 1]) % mod;//j+1個列裡任選乙個即可有總共k個放了兩個炮的列,同時j+1個放1個炮的列也變成了j個 

dp[i][j][k] = (dp[i][j][k] + j * (m - (j+k-1) ) * dp[i - 1][j][k - 1]) % mod;//j列任選乙個,空列任選乙個, 都放乙個,即可有k個放了兩個炮的列乘法原理。

dp[i][j][k] = (dp[i][j][k] + (m - j - k + 1) * dp[i - 1][j - 1][k]) % mod//空列放乙個,即可有j個放了乙個炮的列。

dp[i][j][k] = (dp[i][j][k] + c(j + 2) * dp[i - 1][j + 2][k - 2]) % mod;//j+2列裡任選兩個。

dp[i][j][k] = (dp[i][j][k] + c(m - j - k + 2) * dp[i - 1][j - 2][k]) % mod;//空列裡任選兩個

code:

#include #define int long long	

const int mod = 9999973;

using namespace std;

int n, m, ans;

int dp[111][111][111];//三維陣列dp[i][j][k]表示前i行內放了有j個只放了乙個炮的列,k個放了兩個炮的列的總方案數

int c(int n) //c(n, 2),n個數裡面選擇2個數的組合數。

signed main()

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

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

ans += dp[n][i][j], ans %= mod;//全放兩個的,全放乙個的和放兩個和放乙個都有的,都有可能出現,所以都要加上;

printf("%lld", ans % mod);

return 0;

}

洛谷 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...