51nod 1327 棋盤遊戲

2021-08-02 17:58:20 字數 1688 閱讀 3409

有乙個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.

之後有n行,每行兩個數left[i],right[i],其中,1<=left[i],right[i]<=m,且 left[i]+right[i] <= m。

output

乙個整數,即符合條件的方案數mod 1,000,000,007後的結果。
input示例

2 4

1 22 1

output示例

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...