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