AHOI2009 中國象棋

2021-08-11 19:25:57 字數 1459 閱讀 7508

題目描述

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

輸入格式:

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

輸出格式:

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

資料範圍

100%的資料中n和m均不超過100

50%的資料中n和m至少有乙個數不超過8

30%的資料中n和m均不超過6

顯然,同一行裡我們最多放2個棋子。

限制我們放棋子的條件是縱列。

我的初步想法是,狀壓把當前行表示出來,記錄前面的列放了棋子數,合法轉移。

先不說這樣一定會t。。**實現就很難。要用到三進製狀壓dp。

void init()//預處理三進製狀態每一位的值  

}

這樣就很麻煩。。而且n,m是100。根本就沒法做。。

然而對於任何乙個狀態,我們並不關心他的具體內容,只關心方案數。我們可不可以處理出轉移的方案數,而不表示具體狀態?

綜上:我們需要一種狀態,既可以體現出縱列的約束,又不表示具體狀態使得轉移方便。

所以f【i】【j】【k】表示前i行,有j列放了乙個棋子,有k列放了2個棋子。

顯然,初始狀態f。

對於每一行,我們的操作有:

1.不放 直接轉移

2.放乙個在無棋子的列。(有n列狀態數則*n)

3.放在乙個有棋子的列。(有n列狀態數*n)

4.放2個,都在無棋子的列(c n 2)

5.放2個,都在有1個棋子的列(c n 2)

6.放2個,乙個在無棋子的列,乙個在有棋子的列(乘法原理 n*m)。

然後轉移最後求一下 σf【n】【j】【k】就好了。

#include

using

namespace

std;

#define ll long long

const ll mod=9999973;

const ll maxn=105;

ll n,m;

inline ll cx2(int x)

ll dp[maxn][maxn][maxn];//f[i][j][k]表示 前i行,有j列放了1個,有k列放了2個。

//j+k+空=m

int main()

}ll ans=0;

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

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

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

return

0;}

AHOI2009中國象棋

狀態很難想。本題難就難在如何定狀態。再看題解之前,我一點思路也沒有。看到題解的狀態表示後,我立刻知道怎麼做了。f i j k 表示至第i行,有j列放1個,有k列放2個。這樣f i j k 即為第i行不放 放1個 放2個的數量總和。狀態轉移方程很長,用到組合的相關知識。i 1時需特殊處理。詳見 inc...

AHOI2009 中國象棋

這次小可可想解決的難題和中國象棋有關,在乙個 n n 行m role presentation style position relative m m列的棋盤上,讓你放若干個炮 可以是 0 0 個 使得沒有乙個炮可以攻擊到另乙個炮,請問有多少種放置方法。大家肯定很清楚,在中國象棋中炮的行走方式是 乙...

AHOI2009 中國象棋

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