數位DP模板題
link
題面
[SCOI2005] 互不侵犯
題目描述
在 \(N \times N\) 的棋盤裡面放 \(K\) 個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各一個格子,共 \(8\) 個格子。
輸入格式
只有一行,包含兩個數 \(N,K\)。
輸出格式
所得的方案數
樣例 #1
樣例輸入 #1
3 2
樣例輸出 #1
16
提示
資料範圍及約定
對於全部資料,\(1 \le N \le 9\),\(0 \le K \le N\times N\)。
思路
設定 dp[i][j][k]表示第 \(i\) 排 狀態用二進位制表示為 \(j\),前 \(i\) 排一共放了 \(k\) 個棋子的方案數。
轉移方程為:
\[dp[i][j][k] = \sum_{j_1} dp[i-1][j_1][k-j]
\]
其中 \(j_1\) 表示上一行的狀態,\(k_j\) 表示上一行放了多少個棋子。
注意:\(j\) 和 \(j_1\) 不能有相鄰的 \(1\)。
時間複雜度為 \(O(n^2k^2)\),可以透過。
程式碼
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,K;
int dp[10][(1<<10)][90];
signed main(){
cin >> n >> K;
dp[0][0][0]=1;
for(int k=1;k<=n;k++){
for(int i=0;i<(1<<n);i++){
for(int j=0;j<(1<<n);j++){
for(int p=0;p<=K;p++) {
if((i&j)|(j<<1&i)|(j>>1&i)|(i<<1&i)) continue;
dp[k][i][p+__builtin_popcount(i)]+=dp[k-1][j][p];
}
}
}
}
int ans=0;
for(int i=0;i<(1<<n);i++){
ans+=dp[n][i][K];
}
cout << ans;
return 0;
}
其他數位DP題目
炮兵陣地
Corn Fields G
邦邦的大合唱站隊