傳送門
這道題看資料範圍<=9,很容易想到是狀壓dp。
根據各位dalao的講述,狀壓dp中經常把每乙個行的情況都壓縮起來,之後進行dp。那麼這樣的話想起dp的狀態就比較簡單,dp[i][j][s]表示列舉到第i行,第i行的狀態為j,算上當前行一共放了s個國王一共有多少種情況。其中j是乙個二進位制串,某一位是1代表該位有國王,否則沒有。
那麼dp方程就是: dp[i][j][s] = sum,其中k是上一行能取到的狀態,num指的是本行這種狀態(j)中一共有幾個國王。其中i,j,k,s都是列舉的。
不過算來直接列舉會超時……思考一下,因為國王是互不侵犯的,所以對於每一行來說,肯定有很多種狀態是根本不可選擇的。那我們先預處理出所有可能存在的情況再去列舉。方法很簡單,對於狀態i,如果i&(i<<1),那麼就說明當前的狀態是不可選擇的。直接排除掉即可。
之後,對於每兩行的情況,我們仿照上面的做法&一下即可。比如當前兩行的狀態為x,y,如果x&y || x&(y<<1)|| (x<<1 )& y說明這兩種狀態之間是不可轉移的(因為會互相侵犯)
這樣進行轉移就可以了,注意要預處理第一行的所有情況。
#include#include#include
#include
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
using
namespace
std;
const
int m = 10
;typedef
long
long
ll;ll read()
while(ch >= '
0' && ch <= '9'
)
return ans *op;
}ll n,k,dp[m][
1<2],gk[1
<1
<<(m+1
)];ll getsum(ll x)
intmain()
}rep(i,
1,cnt) ans +=dp[n][i][k];
printf(
"%lld\n
",ans);
return0;
}
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的題是乙個套路 具體實現也基本一樣 就是記錄的狀態...