中國象棋這道題才看到的時候,畏難情緒很重啊,先介紹題目,大意是在n行
m列的棋盤上,放若干個炮可以是
0個,使得沒有任何乙個炮可以攻擊另乙個炮。請問有多少種放置方法。
考試的時候沒有其他的想法,就只想暴力騙分,用乙個一維的標記陣列,再用乙個遞迴,每排最多放兩個。後面想來,完全可以把每排最多放兩個的情況細化。1.不放 2.放1個 3.放兩個。
定義狀態f[i][j][k]表示在棋盤的前i行放置炮,使得m列中有1個炮的列數為j,有2個炮的列數為k的方案數。
考慮第i行怎麼放,分為以下幾種情況:
1、 如果第i行沒有放置任何炮,則方案數為:f[i-1][j][k]
2、 如果第i行放置了1個炮
① 如果這個炮所放置的列上的炮數量為0(前i-1行),說明前i-1行炮數為1的列數肯定是j-1,則對應的方案為:f[i-1][j-1][k]*(m-(j-1)-k)
② 如果這個炮所放置的列上的炮數量為1(前i-1行),說明前i-1行炮數為1的列數肯定是j+1,炮數為2的列數肯定是k-1,這樣通過在i行選擇乙個炮數為1的列放置炮,炮數為1的列數會減1,炮數為2的列數會加1,所以對應的方案為:f[i-1][j+1][k-1]*(j+1)
3、如果第i行放置了2個炮
① 如果這2個炮所放置的列上的炮數量為0(前i-1行),說明前i-1行炮數為1的列數肯定是j-2,則對應的方案為:f[i-1][j-2][k]*c(m-(j-2)-k,2)
② 如果這2個炮所放置的列上的炮數量為1(前i-1行),說明前i-1行炮數為1的列數肯定是j+2,炮數為2的列數肯定是k-2,這樣通過在i行選擇兩個個炮數為1的列放置炮,
炮數為1的列數會減2,炮數為2的列數會加2,則對應的方案為:f[i-1][j+2][k-2]*c(j+2,2)
③ 如果兩個炮乙個放置炮數為0的列(前i-1行),乙個放置在炮數為1的列(前i-1行),說明前i-1行炮數為1的列數肯定是j,炮數為2的列數肯定是k-1,答案為f[i-1][j][k-1]*(m-j-(k-1))*j
分析這道題,一定要抓好分類物件是放幾個炮,不然就會有諸如f[i-1][j][k-1]*c(m-j,2)的異想天開。
另外乙個理解比較容易一些
設f[i][j][k]表示我們要在第i行到n行的棋盤中放置炮,其中前i-1行炮數為1的列數為j,炮數為2的列數為k,在這樣的前提下一共有多少放置方案
考慮第i行:
1、 如果放置0個炮,方案數為f[i+1][j][k]
2、 如果放1個炮,考慮炮的位置
① 放在前i行炮數為0的列,方案=f[i+1][j+1][k]*(m-j-k)
② 放在前i行炮數為1的列,方案=f[i+1][j-1][k+1]*j
3、 如果放2個炮,考慮以下情況:
① 放在前i行炮數為0的列,方案=f[i+1][j+2][k]*c(m-j-k,2)
② 放在前i行炮數為1的列,方案=f[i+1][j-2][k+2]*c(j,2)
③ 乙個放在炮數為0的列,乙個放在炮數為1的列,方案=f[i+1][j][k+1]*(m-j-k)*j
這樣就可以了,再注意一些細節和邊界條件,比前一種好理解*/
乙個順推乙個倒推
下面提供順推的**
#include
using namespace std;
const int mo=9999973;
long long n,m,f[111][111][111];
long long ans=0;
int main()}}
for(int i=0;i<=m;i++)
}printf("%lld",ans);;
return 0;
}
中國象棋2
using system using system.collections.generic using system.linq using system.text using system.drawing namespace chinesechess public override bool mov...
DP 中國象棋
這次小可可想解決的難題和中國象棋有關。在乙個 n 行 m 列的棋盤上,讓你放若干個炮 可以是 0 個 使得沒有任何乙個炮可以攻擊另乙個炮,請問有多少種放置方法。大家肯定很清楚,在中國象棋中炮的行走方式是 乙個炮能攻擊到另乙個炮,當且僅當它們在同一行或同一列中,且它們之間恰好有乙個棋中。你也來和小可可...
中國象棋主流象棋引擎分析
象棋旋風與佳佳象棋,從出現以來就廣泛吸引住了人們的眼球。在那個奇兵與大聖逐漸沒落的年代,旋風與佳佳的接連出現為象棋軟體的發展注入了新的活力。兩個軟體都採取了新的演算法,使得棋力相比過去的軟體有了較大幅度的增長,一時間風靡網路。這兩個軟體都開發了很多個版本,直到現在也沒有停息。但新版本採用了非常先進的...