LightOJ 1061 1061 - N Queen Again(状压dp)
2015-12-11 01:21
591 查看
题意:
给定一个8∗8棋盘有8个皇后,问最少移动多少步可以使得皇后不互相攻击,移动的时候可以移动8个方向,但是皇后不能互相跨越
分析:
如果暴力移动的话,然后判断终态是否合法,复杂度非常高,但是我们提前预处理出所有8皇后的解的方案,只有92种
然后跑带权匹配就可以了,这里用状压dp就可以
问题来了,权值如何计算呢,有一个转化,皇后不能互相跨越这个条件其实是没用的,可以等价为先移动阻挡的皇后,两种需要的步数是一样的
问题解决,复杂度为O(92∗82∗28)
代码:
给定一个8∗8棋盘有8个皇后,问最少移动多少步可以使得皇后不互相攻击,移动的时候可以移动8个方向,但是皇后不能互相跨越
分析:
如果暴力移动的话,然后判断终态是否合法,复杂度非常高,但是我们提前预处理出所有8皇后的解的方案,只有92种
然后跑带权匹配就可以了,这里用状压dp就可以
问题来了,权值如何计算呢,有一个转化,皇后不能互相跨越这个条件其实是没用的,可以等价为先移动阻挡的皇后,两种需要的步数是一样的
问题解决,复杂度为O(92∗82∗28)
代码:
// // Created by TaoSama on 2015-12-10 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; #define pr(x) cout << #x << " = " << x << " " #define prln(x) cout << #x << " = " << x << endl const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; typedef pair<int, int> Point; int vis[3][20]; //column, main, vice diagonal Point goal[8], s[8]; int ans, g[8][8], f[10][1 << 8]; int get(int i, int j) { if(s[i].first == goal[j].first && s[i].second == goal[j].second) return 0; if(s[i].first == goal[j].first || s[i].second == goal[j].second) return 1; if(s[i].first - s[i].second == goal[j].first - goal[j].second) return 1; if(s[i].first + s[i].second == goal[j].first + goal[j].second) return 1; return 2; } void gao() { for(int i = 0; i < 8; ++i) for(int j = 0; j < 8; ++j) g[i][j] = get(i, j); memset(f, 0x3f, sizeof f); f[0][0] = 0; for(int i = 0; i < 8; ++i) { for(int j = 0; j < 1 << 8; ++j) { if(f[i][j] == INF) continue; for(int k = 0; k < 8; ++k) { if(j >> k & 1) continue; f[i + 1][j | 1 << k] = min(f[i + 1][j | 1 << k], f[i][j] + g[i][k]); } } } ans = min(ans, f[8][(1 << 8) - 1]); } void dfs(int row) { if(row == 8) { gao(); return; } for(int i = 0; i < 8; ++i) { if(vis[0][i] || vis[1][row - i + 8] || vis[2][row + i]) continue; goal[row] = Point(row, i); vis[0][i] = vis[1][row - i + 8] = vis[2][row + i] = 1; dfs(row + 1); vis[0][i] = vis[1][row - i + 8] = vis[2][row + i] = 0; } } int main() { #ifdef LOCAL freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin); // freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); int t; scanf("%d", &t); int kase = 0; while(t--) { int idx = 0; for(int i = 0; i < 8; ++i) { char buf[10]; scanf("%s", buf); for(int j = 0; j < 8; ++j) if(buf[j] == 'q') s[idx++] = Point(i, j); } ans = INF; dfs(0); printf("Case %d: %d\n", ++kase, ans); } return 0; }
相关文章推荐
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题
- LeetCode之Maximum Product Subarray
- DP Flow