題解 P2051 AHOI2009 中國象棋

2022-05-07 21:42:13 字數 1239 閱讀 6601

題目鏈結

題目大意:求在\(n\)行\(m\)列的棋盤上放置若干個炮使得它們互不攻擊的方案數,對\(9999973\)取模

動態規劃,計數

分析:沒有炮互相攻擊等價於沒有三個炮在同一行/列

考慮用\(f[i][m_1][m_2]\)表示前\(i\)行,有\(m_1\)列有乙個炮,\(m_2\)列有兩個炮的方案數

可以用刷表法降低思維難度

初始條件:

\(f[1][0][0] = 1\)

\(f[1][1][0] = m\)

\(f[1][2][0] = c_m^2\)

這個比較簡單,轉移可以大力分類討論,即討論第\(i + 1\)行的放置個數,以及放置方案

\(f[i + 1][m_1][m_2] += f[i][m_1][m_2]\)

\(f[i + 1][m_1 + 1][m_2] += f[i][m_1][m_2] \times (m - m_1 - m_2)\)

\(f[i + 1][m_1 - 1][m_2 + 1] += f[i][m_1][m_2] \times m_1\)

\(f[i + 1][m_1 + 2][m_2] += f[i][m_1][m_2] \times c_^2\)

\(f[i + 1][m_1][m_2 + 1] += f[i][m_1][m_2] \times m_1 \times (m - m_1 - m_2)\)

\(f[i + 1][m_1 - 2][m_2 + 2] += f[i][m_1][m_2] \times c_^2\)

然後注意一下邊界條件,避免非法狀態和非法轉移即可

#include using namespace std;

typedef long long ll;

const int maxn = 128,mod = 9999973;

int n,m;

ll f[maxn][maxn][maxn],ans;

inline ll c2(ll x)

int main()

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

for(int m2 = 0;m1 + m2 <= m;m2++)

ans += f[n][m1][m2],ans %= mod;

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

return 0;

}

P2051 AHOI2009 中國象棋

這次小可可想解決的難題和中國象棋有關,在乙個 n 行 m 列的棋盤上,讓你放若干個炮 可以是 0個 使得沒有乙個炮可以攻擊到另乙個炮,且它們之間恰好 有乙個棋子。你也來和小可可一起鍛鍊一下思維吧!一行包含兩個整數 n,m之間由乙個空格隔開。總共的方案數,由於該值可能很大,只需給出方案數模 99999...

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 中國象棋 DP

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