1. 程式人生 > >BZOJ 1087 互不侵犯King 狀態壓縮DP

BZOJ 1087 互不侵犯King 狀態壓縮DP

num 使用 break fine getc 一起 php min sizeof

題目鏈接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1087

題目大意;

在N×N的棋盤裏面放K個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各一個格子,共8個格子。

思路:

狀態壓縮,預處理出每一行的合法狀態,連續的兩個1在一起的狀態為不合法狀態。

預處理出從上一行到下一行的合法情況,直接每一行推過來即可。

 1 #include<bits/stdc++.h>
 2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用於函數,會超時 4 #define Min(a, b) ((a) < (b) ? (a) : (b)) 5 #define Mem(a) memset(a, 0, sizeof(a)) 6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1)) 7 #define MID(l, r) ((l) + ((r) - (l)) / 2) 8 #define lson ((o)<<1) 9 #define
rson ((o)<<1|1) 10 #define Accepted 0 11 #pragma comment(linker, "/STACK:102400000,102400000")//棧外掛 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while (ch<0||ch>9){if (ch==-) f=-1;ch=getchar();} 17 while (ch>=0&&ch<=9){x=x*10+ch-
0;ch=getchar();} 18 return x*f; 19 } 20 typedef long long ll; 21 const int maxn = 2000000 + 10; 22 const int MOD = 1000000007;//const引用更快,宏定義也更快 23 const int INF = 1e9 + 7; 24 const double eps = 1e-10; 25 const double pi = acos(-1); 26 27 bool Map[520][520]; 28 bool no[520];//判斷狀態i是否不合法 29 ll dp[10][520][100];//dp[i][j][k] 表示第i行狀態為j,且當前放置的數目為k 30 int n, k; 31 void init() 32 { 33 for(int x = 0; x < (1<<n); x++) 34 for(int i = 0; i < n - 1; i++) 35 if((x&(1<<i))&&(x&(1<<(i+1)))){no[x] = 1;break;} 36 for(int x = 0; x < (1<<n); x++)if(!no[x]) 37 { 38 for(int y = 0; y < (1<<n); y++)if(!no[y]) 39 { 40 bool flag = 1; 41 for(int i = 0; i < n; i++)if(x&(1<<i)) 42 { 43 if(y&(1<<i)){flag = 0; break;} 44 if(i != 0 && (y&(1<<(i-1)))){flag = 0; break;} 45 if(i != n && (y&(1<<(i+1)))){flag = 0; break;} 46 } 47 Map[x][y] = flag; 48 } 49 } 50 } 51 inline int f(int x) 52 { 53 int ans = 0; 54 for(int i = 0; i < n; i++)if(x&(1<<i))ans++; 55 return ans; 56 } 57 int main() 58 { 59 cin >> n >> k; 60 init(); 61 for(int i = 0; i < (1<<n); i++)if(!no[i])dp[1][i][f(i)] = 1; 62 for(int i = 2; i <= n; i++) 63 for(int x = 0; x < (1<<n); x++)if(!no[x])//該行狀態 64 for(int y = 0; y < (1<<n);y++)if(!no[y] && Map[y][x])//上一行狀態 65 { 66 int tmp = f(x); 67 for(int num = 0; num + tmp <= k; num++) 68 dp[i][x][num + tmp] += dp[i - 1][y][num]; 69 } 70 ll ans = 0; 71 for(int i = 0; i < (1<<n); i++)if(!no[i])ans += dp[n][i][k]; 72 cout<<ans<<endl; 73 return 0; 74 }

BZOJ 1087 互不侵犯King 狀態壓縮DP