首先,養成乙個思路:資料這麼小?狀壓dp!
然後翻題解可以這麼定義狀態:
定義\(dp[i][j][k]\)為前\(i\)行中,第\(i\)行狀態為\(j\),前\(i\)行已放置\(k\)個國王的方案數。
顯然一行的狀態只與前一行的有關,所以只需要記錄一行的狀態。
但是一行的狀態好像很難存啊!難道複製乙個陣列進去嗎?
其實,對於每乙個點, 只有放置或不放置之分,所以可以使用乙個整數,用二進位制表示。
同時,\(n \leq 9\),只需要\(2^9 = 512\)的空間即可裝下這麼乙個狀態,所以是完全可行的。
發現,只有三種情況會不合法,無法轉移,分別是:
上下有重合的。只需要兩個二進位制進行&,如果不為0就有這種情況。
左上和右下重合。只需要下面的二進位制左移一位,再進行&操作,如果不為0就有這種操作。
右上和左下重合。同理只需要上面的二進位制數左移。
只要篩除掉這三種情況即可。
話說我們可以預處理出所有的狀態,可以直接篩除掉絕對不可能的狀態,減小常數。
然後具體看**吧。
**:
#includeconst int maxn = 11;
long long dp[maxn][1 << maxn][maxn * maxn];
long long ans;
int status[1 << maxn], tot;
int n, m;
int maxl;
int sum[maxn];
int lowbit(int x)
int getnum(int x)
return t;
}int main()
} for(int i = 2; i <= n; i++)
}} }
for(int i = 1; i <= n; i++)//可能不在n結束 }
printf("%lld\n", ans);
}
P1896 SCOI2005 互不侵犯
p1896 scoi2005 互不侵犯 資料不大,時間複雜度很高也差不多能過。使用狀壓dp dp i j k 表示到第i行,狀態為j,選了k個人 然後就是轉移,轉移的難點就是快速判斷 判斷的話,我們整體考慮。然後乙個狀態是否有相鄰的國王。用它本身按位與它本身右移 左移 若結果為0,則說明無相鄰的國王...
P1896 SCOI2005 互不侵犯
在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。注 資料有加強 2018 4 25 只有一行,包含兩個數n,k 1 n 9,0 k n n 所得的方案數 輸入樣例 1 複製3 2 輸出樣例 1 複製...
P1896 SCOI2005 互不侵犯King
在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。輸入格式 只有一行,包含兩個數n,k 1 n 9,0 k n n 輸出格式 所得的方案數 輸入樣例 1 3 2 輸出樣例 1 16 用二進位制壓縮狀態...