矩陣中的DP題 放象棋

2021-06-16 16:11:40 字數 1464 閱讀 9651

題目的意思很簡單:在n * m的矩陣中放置若干個炮(可以不放),使得沒有乙個炮可以攻擊另外乙個炮。炮的攻擊方式就不用多說了。答案mod 9999973。

這個題目一開始我想得很接近了,但沒想到用dp,覺得是組合數學。首先可以把問題轉化一下:沒有一列或一行有兩個以上的炮,這樣炮於炮之間就不能攻擊了。也就是說,每行或每列,要麼不放炮,要麼放乙個或兩個,有三種可能。又因為行列是交錯的,每放乙個炮,對行列都有影響。以前做過一道類似的題,好像叫「一筆畫」,是對每一行進行處理,然後把列的資訊儲存下來。這題也是這樣。

記f(i,j,k)為當前對第i行決策,已經有j列有乙個炮,k列有兩個炮,至於沒有炮的有多少列,這個只需要用總列數m - j - k,把m - j - k記為p。那麼,對於這一行,我們最多只能放兩個棋, 有種方案:

1.放乙個在沒有炮的列,那麼前乙個狀態是f(i - 1,j - 1,k),那麼有p + 1列是沒有炮的,放的棋子就有p + 1種選擇。

2.放兩個在沒有炮的列,那麼前乙個狀態是f(i - 1,j - 2,k),那麼有p + 2列是沒有炮的,放的棋子就有c(p + 2, 2)種選擇。

3.放乙個在有乙個炮的列,那麼前乙個狀態是f(i - 1,j + 1,k - 1),有j + 1列是有乙個炮的,放的棋子就有j + 1種選擇。

4.放兩個在有乙個炮的列,那麼前乙個狀態是f(i - 1,j + 2,k - 2),有j + 1列是有乙個炮的,放的棋子就有c(j + 2,2)種選擇。

5.放乙個在沒有炮的列,再放乙個在有乙個炮的列,那麼前乙個狀態是f(i - 1,j,k - 1),選擇有(p + 1) * (j + 1)。

6.不放,前乙個狀態是f(i - 1,j,k)。

最後輸出f(n)的和就可以了。

#include #include using namespace std;

typedef long long ll;

const ll mod = 9999973;

const int n = 107;

int n, m;

ll f[n][n], g[n][n];

// flag為false,c(a, 1),為true,c(a, 2)

ll c(int a, bool flag)

void plus(ll &s, ll t)

int main()

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

for (int b = 0; b <= m; b ++) g[a][b] = f[a][b]; }

ll ans = 0;

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

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

plus(ans, f[a][b]);

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

return 0;

}

兩個矩陣中的dp題的差異

給定乙個由 0 和 1 組成的矩陣,找出每個元素到最近的 0 的距離。分析 很容易想到dp i j min dp i 1 j dp i j 1 dp i 1 j dp i j 1 出口是若m i j 0,則dp i j 0。但是有個問題,兩個相鄰的1,求當前值需要知道另乙個,求另乙個需要當前值,這樣...

bzoj2510 矩陣乘法 DP 弱題

description 有m個球,一開始每個球均有乙個初始標號,標號範圍為1 n且為整數,標號為i的球有ai個,並保證 ai m。每次操作等概率取出乙個球 即取出每個球的概率均為1 m 若這個球標號為k k n 則將它重新標號為k 1 若這個球標號為n,則將其重標號為1。取出球后並不將其丟棄 現在你...

AHOI2009中國象棋 巧妙dp

題目意思是在乙個n m n,m 100 的矩形裡放任意多個棋子,滿足任一行任一列都最多只有2個棋子,求方案數。考慮用dp,設三維dp i j k 代表列舉到i行,有j列只有1個棋子,k列有2個棋子的方案數,那麼放0個棋子的列數就是m j k了。在第i行只能放0,1,2個棋子,那麼我們模擬一下,就可以...