time limit:1000ms memory limit:65536k
total submit:95 accepted:38
description
在n ∗n
(n≤20
)n*n(n≤20)
n∗n(n≤
20)的方格棋盤上放置n
nn個車(可以攻擊所在行、列),有些格仔不能放,求使它們不能互相攻擊的方案總數。
input
第一行為棋盤的大小n
nn第二行為障礙的數量m
mm第三行到第m+3
m+3m+
3為mm
m個障礙
output
總數sample input42
1 12 2
sample output
14解題思路
狀態壓縮遞推(states compressing recursion,scr)
我們一行一行放置。
取棋子的放置情況作為狀態,某一列如果已經放置棋子則為1
11,否則為0
00。這樣,乙個狀態就可以用乙個最多20
2020
位的二進位制數表示。
例如n =5
n=5n=
5,第1、3
、41、3、4
1、3、
4列已經放置,則這個狀態可以表示為01101
01101
0110
1(從右到左)。設f[s
]f[s]
f[s]
為達到狀態s
ss的方案數,則可以嘗試建立f
ff的遞推關係。
考慮n =5
,s=01101
n=5,s=01101
n=5,s=
0110
1,因為我們是一行一行放置的,所以當達到s
ss時已經放到了第三行。又因為一行能且僅能放置乙個車,所以我們知道狀態s
ss一定來自(沒障礙物的情況下):
1. 前兩行在第3、4列放置了棋子(不考慮順序,下同),第三行在第1列放置;
2. 前兩行在第1、4列放置了棋子,第三行在第3列放置;
3. 前兩行在第1、3列放置了棋子,第三行在第4列放置。
圖示:
在列舉s中的1的時候判斷一下是否有障礙物即可
**
#include
#include
#include
#include
#include
using namespace std;
const int maxn=
1<<
20;
int n,m,num,x,y;
long long vis[25]
,f[maxn]
;int main()
f[0]=
1;for(int i=
1;i<
1<<
(n);i++
)//列舉可能出現的狀態
printf
("%lld"
,f[(
1<
]);}
狀態壓縮DP
首先,我們以一道狀壓經典題tsp來引入。tsp問題 一張圖上有n個點,給定相應的鄰接矩陣,需要求出從0號節點出發,經過且只經過每個頂點一次,最後仍回到0號節點的最小邊權。思路 假設現在已訪問過的頂點集合 起點0當作還未訪問過的頂點 為s,當前所在頂點為v,用dp s v 表示從v出發訪問剩餘的所有頂...
狀態壓縮DP
theme 給定乙個n m的玉公尺田,1 n,m 12。值為0表示不能在該塊種草,為1表示可以。現在要在其上中若干草地,要求任意草地間不相鄰 沒有公共邊 問不考慮草地個數的情況下,有多少種種植的方案?solution 用dp。又範圍很小,所以考慮狀態壓縮dp,另dp i j 表示從前i行種植,最後一...
狀態壓縮DP
總結狀壓dp轉移的方法 若某個狀態下可以對下 1.按二進位制讀入資料 2.列舉所有方案,如果合理 一行中沒有兩兩相鄰的 就儲存 i i 1 3.因為每一層的狀態只受上一層影響,因此迴圈兩次所有合理方案,為每乙個方案找到一系列下一層合理方案 4.遍歷每一行,並遍歷每一行的所有合理方案,若與預處理不矛盾...