SCOI2005 互不侵犯

2022-06-17 21:42:14 字數 1348 閱讀 9380

題目描述

在n×n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。

由於每擺上乙個棋子,需要檢視周圍9個位置,導致搜尋的複雜度直接**(\(n^2\)個格仔裡選k個格仔滿足條件,搜尋複雜度不太好估計,但是\(c(k,n^2)\)一定很大)

因此需要預處理每一行的合法狀態,然後進行遞推(狀壓dp),每一位所記錄的狀態都是合法的

對於每一行,先列舉這一行的預備狀態,然後列舉這一行的預備容量(類似揹包列舉容量),再列舉上一行的狀態(這個狀態滿足遞推關係所以滿足題目條件),如果兩行judge合法則從上一行的狀態轉移到這一行

設上一行的狀態下標為k,這一行的狀態下標為j(其所包含1的數量為num[j])

即寫出狀態轉移方程:\(dp[i][l][j] += dp[i - 1][l - num[j]][k]\)(類似揹包,如果l-num[j]有狀態會被加上來,沒有就當無事發生);

別忘了初始狀態為dp[0][0][0]=1,即第0行沒有擺棋子的0號狀態為合法狀態

最後統計第n行有k個棋子的每個狀態所滿足條件的合法狀態數即可

記得開long long

#pragma gcc optimize(2)

#include#define ll long long

#define fastio ;

using namespace std;

const int inf = 1e9 + 7;

const int maxn = 1e4 + 10;

vector>zt;

ll dp[11][200][200];

ll judge(ll x)

else

flag = 0;

x >>= 1;

}return cnt;

}int main()

); for (int i = 1; i < 1 << n; i++));}

}dp[0][0][0] = 1;

for (int i = 1; i <= n; i++)

for (int j = 0; j < zt.size(); j++)

for (int l = zt[j].second; l <= k; l++)

for (int k = 0; k < zt.size(); k++)

ll ans = 0;

for (int i = 0; i < zt.size(); i++)

ans += dp[n][k][i];

cout << ans;

return 0;

}

SCOI2005 互不侵犯

在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。只有一行,包含兩個數n,k 1 n 9,0 k n n 方案數3 2 同sgu223 include include include include ...

SCOI2005 互不侵犯

題目描述 在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。輸入格式 只有一行,包含兩個數n,k 1 n 9,0 k n n 輸出格式 所得的方案數 ly最可愛啦 這題。想了5分鐘,寫了10分鐘,調了...

SCOI2005 互不侵犯

在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。兩個數n,k 1 n 9,0 k n n 方案數。3 2果然啊 狀壓題都是乙個套路 和前面那個noi的題是乙個套路 具體實現也基本一樣 就是記錄的狀態...