這次小可可想解決的難題和中國象棋有關,在乙個n行m列的棋盤上,讓你放若干個炮(可以是0個),使得沒有乙個炮可以攻擊到另乙個炮,請問有多少種放置方法。大家肯定很清楚,在中國象棋中炮的行走方式是:乙個炮攻擊到另乙個炮,當且僅當它們在同一行或同一列中,且它們之間恰好 有乙個棋子。你也來和小可可一起鍛鍊一下思維吧!
輸入格式:
一行包含兩個整數n,m,之間由乙個空格隔開。
輸出格式:
總共的方案數,由於該值可能很大,只需給出方案數模9999973的結果。
輸入樣例#1:
1 3
輸出樣例#1:
7
樣例說明
除了3個格仔裡都塞滿了炮以外,其它方案都是可行的,所以一共有2*2*2-1=7種方案。
資料範圍
100%的資料中n和m均不超過100
50%的資料中n和m至少有乙個數不超過8
30%的資料中n和m均不超過6
首先可以知道可行的方案就是每行每列的放的炮數<=2
50%資料是狀壓dp,然後我們發現,他的矩形是規則的而且沒有障礙一類的。
那麼答案就跟他的每個具體排列沒有直接關係,直接用dp[i][j]表示到當前行為止有多少炮數為1的列和炮數為2的列
由於每行也最多只能放兩個炮,所以可以用dp[i][j]
轉移到dp[i-1][j+1](有乙個炮數為1的列在此行放上乙個炮)
轉移到dp[i+1][j](有乙個炮數為0的列在此行放上乙個炮)
轉移到dp[i-2][j+2](有兩個炮數為1的列在此行放上乙個炮)
轉移到dp[i+2][j](有兩個炮數為0的列在此行放上乙個炮)
轉移到dp[i][j+1](有乙個炮數為0的列在此行放上乙個炮,有乙個炮數為1的列在此行放上乙個炮)
//serene#include#include#include#include#include#includeusing namespace std;
const int maxn=100+10,mod=9999973;
long long n,m,dp[maxn][maxn],f[maxn][maxn],ans;
int main()
memcpy(dp,f,sizeof(f));memset(f,0,sizeof(f));
}for(int j=0;j<=m;++j) for(int k=0;k<=m-j;++k) ans=(ans+dp[j][k])%mod;
printf("%lld",ans);
return 0;
}
洛谷 P2051 中國象棋
orz stdcall 首先要想出來,每行最多只能放兩個棋子,這是顯然的 於是決策就是一行一行地處理 30分的做法就是裸的列舉,暴搜,列舉這一行放 放幾個 然後想到了壓位dp,按3進製表示當前棋盤的狀態,即某一列沒有棋子,或者有乙個,兩個棋子,能過50分 接著可以發現,棋子的順序是無所謂的,並不需要...
洛谷P2051 中國象棋
題意 在乙個n行m列的棋盤上,讓你放若干個炮,可以是0個,使得沒有乙個炮可以攻擊另乙個炮,請問有多少種放置方法。題解 因為每一行每一列的炮的數量 2 考慮開dp陣列儲存有幾列放了乙個炮,有幾列放了兩個炮 dpi k 表示放了前i行,有j列是有乙個棋子,有k列是有2個棋子的合法方案數 空的序列就是合法...
洛谷 P2051 中國象棋 題解
題面 狀態可能不太好想,設f i j k 表示前i行其中有j行是放乙個炮,有k行是放兩個炮的合法方案數 那麼 f i 1 j k f i j k 在這一行不放任何棋子 f i 1 j 1 k f i j k m k j 在剩餘的m k j個空行中隨機選擇乙個放下乙個炮 f i 1 j 1 k 1 f...