SCOI2005 互不侵犯

2022-05-05 18:39:09 字數 1193 閱讀 6395

傳送門

這道題看資料範圍<=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的題是乙個套路 具體實現也基本一樣 就是記錄的狀態...