有乙個n行m列的棋盤,即該棋盤被分為n*m格。現在向棋盤中放棋子,每個格仔中最多放乙個棋子,也可以乙個不放。放完棋子後需要滿足如下要求:
1)對於第i行來說,其從左往右的前left[i] 個格仔(即最左側的left[i] 個連續的格仔)中恰好一共有1個棋子;
2)對於第i行來說,其從右往左的前right[i]個格仔(即最右側的right[i]個連續的格仔)中恰好一共有1個棋子;
3)對於每一列來說,這一列上的所有格仔內含有的棋子數不得超過1個。
其中,1)與2)條件中,對所有 i 滿足 left[i]+right[i] <= m,即兩個區間不會相交。
問,符合上述條件情況下棋子的不同放法一共有多少種?輸出放法的個數 mod 1,000,000,007後的結果。
例如樣例中,只有如下圖一種方法。
第一行包含兩個整數,n,m,其中1<=n<=50,2<=m<=200.output之後有n行,每行兩個數left[i],right[i],其中,1<=left[i],right[i]<=m,且 left[i]+right[i] <= m。
乙個整數,即符合條件的方案數mod 1,000,000,007後的結果。input示例
2 4output示例1 22 1
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
神奇dp+思路~
用f[i][j][k]表示當前i列,一共放了j枚棋子,有k行的右區間不滿足。
不需要把a陣列排序,排了也沒有用的哼。
我們顯然不能同時dp左右區間,所以我們只能在更新的時候強制滿足左區間,dp右區間。
因為每一列最多只能填1個,所以我們可以列舉我們把這個棋子填在什麼位置。
對於每一列i,我們預處理出l為左區間的右邊界==i的行數,r為右區間的左邊界==i的行數,block為i既不在左區間也不在右區間的行數。
那麼就有四種放置情況:滿足乙個左區間,滿足乙個右區間,放在乙個中間區域(即乙個block),以及不放。
滿足左區間時,我們從已有左區間中選擇乙個,然後強制假設之前的j枚棋子中有左區間-1個剛好滿足了左區間,其餘同理。
我列舉區間的時候i是從0開始的導致**很難看,i+1表示的都是真正的i的位置!
#include#include#includeusing namespace std;
#define mod 1000000007
#define ll long long
int n,m,f[202][202][52],c[202][202],mi[202],ans,l,r,block;
struct nodea[51];
int read()
while(ch>='0' && ch<='9')
return x*f;
}void add(int &a,int b)
int main()
}} for(int i=0;i<=m;i++) add(ans,f[m][i][0]);
printf("%d\n",ans);
return 0;
}
棋盤遊戲 51Nod 1327
題解 在放置棋子時僅僅要求左右滿足條件與n的順序無關,考慮乙個二維dp陣列,dp i j 代表放到了第i列還有j列沒有放棋子,但是這個二維dp沒有維護右限的資訊,所以考慮增加一維代表有多少行到達了右限但沒有棋子,將l和r區間的限制統計,可以得到dp轉移方程 dp a 1 b 1 l a 1 c r ...
51nod1327 棋盤遊戲 dp
description 有乙個n n 行m role presentation style position relative m m列的棋盤,即該棋盤被分為n m n m 格。現在向棋盤中放棋子,每個格仔中最多放乙個棋子,也可以乙個不放。放完棋子後需要滿足如下要求 1 1 對於第i行來說,其從左往...
題解 51nod 1327 棋盤遊戲
51nod 1327 棋盤遊戲 求合法方案數 這題挺妙的,雖然可能妙得不是非常直觀 首先,因為考慮每一列只能填乙個,考慮怎麼填 宣告 l i 為以 i 為左區間右端點的行數,r i 為以 i 為右區間左端點的行數,mid i 為第 i 列上有多少沒有被左右區間覆蓋的行數 於是可以設計乙個狀態 f i...