P1896 互不侵犯 狀壓DP

2021-09-21 02:14:18 字數 2412 閱讀 8718

目錄題目

分析變數定義

剔除左右相鄰的狀態

計算king[ ] 、state[ ]

如何動態規劃?

如何表示限制條件

原博主的**

寫在最後

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

輸入格式:

只有一行,包含兩個數n,k ( 1 <=n <=9, 0 <= k <= n * n)

輸出格式:

所得的方案數

參考部落格

對原博主的**進行了自己的理解,並改變了敘述方式和順序。

狀態壓縮的主要思想是,用二進位制來表示當前的狀態,然後用二進位制對應的十進位制數來進行儲存。

比如某一行的國王排列是(有,無,有,無,無,有)。我們用1來代表有,0代表無。那麼對應的二進位制為101001,

我們的king[ j ] 陣列表示的是 狀態j 下的國王數。所以 king[41]=3.   狀態41有3個國王。

同時,state[ i ]陣列,就是第 i 個狀態的 國王排列所對應的狀態(十進位制)。 如果這個排列是第乙個,那麼 ans[1]=41;

ans是狀態(剔除左右相鄰)的總數。

我們需要對這些狀態,左右相鄰的狀態進行剔除。

if( ! ((i<<1)&i )  )//不相鄰

有n*n的棋盤,對於每一行,最多有000...000 --- 111...111這麼多種可能的狀態。對應的十進位制是0到

int tot=(1<>=1;//右移一位}}

}

當前行的狀態,跟上一行的狀態(國王的擺放位置,前面所有行已經用了多少個國王)有關。

(剔除 左右相鄰的狀態  後的總數)。這樣,dp時,才能考慮上下行的關係。

初始條件是第一行狀態。

long long dp[10][15000][80]; //dp[i][j][k]表示第i行,狀態為j,前面擺了k個國王時,方案數;

long long king[7777777]; //king[j]表示,在狀態為j時,使用的國王數量

for(int i=1;i<=ans;i++)// 對於第一行

}

我們仍舊利用,動態規劃中,j表示本行狀態,p表示前一行狀態。(左右相鄰狀態初始化中,已經剔除)

(1)如何表示上下相鄰

if(state[j]&state[p]) continue;//上下相鄰
一旦上下相鄰,就必然會出現1&1的情況,結果非0。

(2)如何表示 左下,右上

if(state[j]&(state[p]<<1)) continue;//本行的右上
(3)如何表示 左上,右下

if((state[j]<<1)&state[p]) continue;//本行的左上角

#include#include#include#include#include#include#include#include#includeusing namespace std;

#define ll long long

ll dp[10][15000][80];

ll state[777777],king[7777777];

ll ans,sum;

ll n,k;

inline void init()}}

}int main()

}for(int i=1;i<=n;i++)//不確定在哪一行用光了國王

for(int j=1;j<=ans;j++)//不確定在那種狀態下

sum+=dp[i][j][k];

cout<

有數量限制的dp,要在dp【】中開一位,表示數量。

資料量較小的時候,要考慮到狀壓dp。

洛谷P1896 互不侵犯 狀壓dp

在n n n nn n的棋盤裡面放k kk個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8 88個格仔。n 9 k n n n 9,k n n n 9 k n n 首先暴搜肯定被否定,時間複雜度是指數級的,所以我們就可用上狀態壓...

互不侵犯(洛谷P1896)

題目 在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。輸入輸出 輸入n,k,輸出有幾種放置方法。n 9,k n 2 樣例輸入輸出 入 3 2 出 16 這道題看範圍就顯然是狀壓dp了吧。其實這道題和...

1896 SCOI2005 互不侵犯 狀壓dp

傳送門 這是一道狀壓dp的經典例題 題目讓輸出所有可能的方案數 很顯然 這是一道動態規劃了 由於國王放置的位置有一定的限制 所以我們要在狀態轉移的過程中增加一維來儲存狀態 我們這一道題假設f i j k 意思是在前i行一共放置了j個國王 第i行國王放置的狀態是k 儲存的值是方案數 首先 我們可以先預...