日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

小国王——状压DP

發布時間:2023/12/20 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小国王——状压DP 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在?n×n 的棋盤上放?k?個國王,國王可攻擊相鄰的?8?個格子,求使它們無法互相攻擊的方案總數。

輸入格式

共一行,包含兩個整數?n?和?k。

輸出格式

共一行,表示方案總數,若不能夠放置則輸出0。

數據范圍

1≤n≤10,
0≤k≤n^2

輸入樣例:

3 2

輸出樣例:

16

思路:

f[i][j][k]:表示前i行放置了j個國王,且第i行的狀態是k?? ??? ?屬性:cnt

首先考慮當前這一行,找到當前這一行所有的合法狀態(即狀態的縱坐標不相鄰),以及合法狀態的合法轉移狀態(因為當前這一行的狀態肯定是上一行轉移過來的,所以只需要考慮上一行的狀態。 那么上一行什么樣的狀態才能轉移成當前的狀態?由題意發現上一行狀態與當前行狀態的縱坐標不能相鄰上下不能相鄰,左右也不能相鄰)以便于狀態轉移計算。

狀態表示:

f[i][j][k]:表示前i行放置了j個國王,且第i行的狀態是k?? ??? ?

屬性:cnt

狀態計算:

f[i][j][k] +=? f[i-1][j-cnt[state]][state]

初始狀態:

f[0][0][0]

目標狀態:

f[n+1][k][0]????????

因為只要這層不擺東西,則上一層 只要合法,那一定可以轉移到這一層的這個0狀態

解決代碼:

#include<iostream> #include<string.h> #include<algorithm> #include<cmath> #include<vector> using namespace std;typedef long long LL;const int N = 11, M = 1 << N, C = N * N;int n, m, k; LL f[N][C][M]; //f[i][j][k]:表示前i行放置了j個國王,且第i行的狀態是k 屬性:cnt int cnt[M]; //用來存儲每個合法狀態中有多少個國王 vector<int> legal; //存放合法狀態數組 vector<int> trans[M]; //存放合法狀態的合法轉移狀態 bool check(int state) //檢查縱坐標是否相鄰 {return !(state&state>>1); }int count(int state) {int cnt = 0;for(int i=0;i<n;i++) if(state>>i&1) cnt++;return cnt; }int main() {cin>>n>>k;//預處理所有狀態for(int i=0;i<1<<n;i++)//檢查當前狀態是否合法if(check(i)){legal.push_back(i);cnt[i] = count(i); }//預處理所有合法狀態的合法轉移狀態 for(auto i:legal)for(auto j:legal) if(!(i&j)&&check(i|j)) //上下不相鄰且左右不相鄰trans[i].push_back(j);f[0][0][0] = 1;for(int i=1;i<=n;i++)for(int j=0;j<=k;j++)for(auto st : legal)for(auto tt : trans[st])if(j-cnt[st]>=0)f[i][j][st] += f[i-1][j-cnt[st]][tt];LL ans = 0; for(auto s : legal)ans += f[n][k][s];cout<<ans; return 0; }

總結

以上是生活随笔為你收集整理的小国王——状压DP的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。