題解 51nod 1327 棋盤遊戲

2022-04-30 04:27:12 字數 1716 閱讀 7779

51nod 1327 棋盤遊戲

求合法方案數

這題挺妙的, 雖然可能妙得不是非常直觀

首先, 因為考慮每一列只能填乙個, 考慮怎麼填

宣告 \(l[i]\) 為以 \(i\) 為左區間右端點的行數, \(r[i]\) 為以 \(i\) 為右區間左端點的行數, \(mid[i]\) 為第 \(i\) 列上有多少沒有被左右區間覆蓋的行數

於是可以設計乙個狀態 \(f[i][j][k]\) 表示當前考慮到了第 \(i\) 列, 有 \(j\) 列沒填, \(k\) 行左端點 \(\le i\) 的右區間沒有填任何棋子的方案數

則能夠考慮第 \(i + 1\) 列的棋子填在**, 而且每次讓左區間強行滿足條件, 即左區間右端點 \(\le i\) 的每乙個左區間都有且僅有一顆棋子

有:第 \(i + 1\) 列的棋子被左區間覆蓋:

\[f[i + 1][j - l[i + 1] + 1][k + r[i + 1]] += f[i][j][k] \times a_^

\]第 \(i + 1\) 列的棋子被右區間覆蓋:

\[f[i + 1][j - l[i + 1]][k + r[i + 1] - 1] += f[i][j][k] \times a_^ \times (k + r[i + 1])

\]第 \(i + 1\) 列的棋子沒有被左區間或右區間覆蓋:

\[f[i + 1][j - l[i + 1]][k + r[i + 1]] += f[i][j][k] \times a_^ \times (mid[i + 1])

\]然後最後答案就是 $$\sum\limits_^ f[m][i][0]$$

sample code

#include #define re register

#define rep(i, a, b) for(re int i = (a); i <= (b); ++ i)

#define rep(i, a, b) for(re int i = (a); i < (b); ++ i)

typedef long long ll;

const ll mod = 1e9 + 7;

const ll n = 2e2 + 5;

int n, m, l, r;

ll mid[n], l[n], r[n];

ll ans, f[n][n][n];

ll fac[n], p[n][n];

void add(ll &x, ll y)

int main()

rep(i, 0, m) p[i][0] = 1;

rep(i, 1, m) rep(j, 1, i)

p[i][j] = (p[i - 1][j - 1] + p[i - 1][j]) % mod;

fac[0] = 1;

rep(i, 1, m) fac[i] = fac[i - 1] * i % mod;

rep(i, 1, m) rep(j, 1, i)

p[i][j] = p[i][j] * fac[j] % mod;

f[0][0][0] = 1;

rep(i, 0, m) rep(j, 0, i) rep(k, 0, n)

if(j >= l[i + 1])

} } rep(i, 0, m) add(ans, f[m][i][0]);

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

return 0;

}

51nod 1327 棋盤遊戲

有乙個n行m列的棋盤,即該棋盤被分為n m格。現在向棋盤中放棋子,每個格仔中最多放乙個棋子,也可以乙個不放。放完棋子後需要滿足如下要求 1 對於第i行來說,其從左往右的前left i 個格仔 即最左側的left i 個連續的格仔 中恰好一共有1個棋子 2 對於第i行來說,其從右往左的前right i...

棋盤遊戲 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行來說,其從左往...