又是一道狀壓DP求方案數的題...數組
多了一個放k個的限制,因而咱們把數組多開一維。ide
f[i][j][k]表示前i行放了j個,第i行狀態爲k的方案數。spa
而後老套路DFS轉移,此次要多記錄一個cnt表示上一行的棋子數。code
而後由於什麼都不放也是能夠轉移的,因此咱們輸出f[m + 1][k][0]即爲最終答案。blog
中間有個num數組是指這個狀態有多少個棋子。io
1 #include <cstdio> 2 3 typedef long long LL; 4 const int N = 10; 5 6 LL f[N + 1][82][1 << N], ans; 7 int pre, m, num[1 << N], cnt, k; 8 9 inline int check(int s) { 10 int a = 0; 11 while(s) { 12 a += s & 1; 13 s >>= 1; 14 } 15 return a; 16 } 17 18 void DFS(int x, int y, int ns) { 19 if(y >= m) { 20 f[x][cnt + num[ns]][ns] += ans; 21 return; 22 } 23 DFS(x, y + 1, ns); 24 if(!y) { 25 if(!((pre >> y) & 1) && !((pre >> (y + 1)) & 1) && cnt + num[ns] < k) { 26 DFS(x, y + 1, ns | 1); 27 } 28 return; 29 } 30 if(!((ns >> (y - 1)) & 1) && !((pre >> (y - 1)) & 1) && !((pre >> y) & 1) && !((pre >> (y + 1)) & 1) && cnt + num[ns] < k) { 31 DFS(x, y + 1, ns | (1 << y)); 32 } 33 return; 34 } 35 36 int main() { 37 scanf("%d%d", &m, &k); 38 int lm = 1 << m; 39 for(int i = 0; i < lm; i++) { 40 num[i] = check(i); 41 } 42 f[0][0][0] = 1; 43 for(int i = 1; i <= m + 1; i++) { 44 for(int j = 0; j < lm; j++) { 45 for(int p = 0; p <= k; p++) { 46 if(!f[i - 1][p][j]) { 47 continue; 48 } 49 ans = f[i - 1][p][j]; 50 pre = j; 51 cnt = p; 52 DFS(i, 0, 0); 53 } 54 } 55 } 56 57 printf("%lld", f[m + 1][k][0]); 58 return 0; 59 }