SPOJ 1771 NQUEEN Yet Another N-Queen Problem
2015-07-29 15:47
288 查看
After solving Solution to the n Queens Puzzle by constructing, LoadingTime wants to solve a harder version
of the N-Queen Problem. Some queens have been set on particular locations on the board in this problem. Can you help him??
The input contains multiple test cases. Every line begins with an integer N (N<=50), then N integers followed, representing the column number of the queen in each rows. If the number is 0, it means no queen has
been set on this row. You can assume there is at least one solution.
For each test case, print a line consists of N numbers separated by spaces, representing the column number of the queen in each row. If there are more than one answer, print any one of them.
n皇后问题,转化为dlx精确覆盖,行列和斜线作为列,不过斜线无需全部覆盖,只是作为约束条件。
转化之前要先剪枝,可以大大减少需要搜索的量.
of the N-Queen Problem. Some queens have been set on particular locations on the board in this problem. Can you help him??
Input
The input contains multiple test cases. Every line begins with an integer N (N<=50), then N integers followed, representing the column number of the queen in each rows. If the number is 0, it means no queen hasbeen set on this row. You can assume there is at least one solution.
Output
For each test case, print a line consists of N numbers separated by spaces, representing the column number of the queen in each row. If there are more than one answer, print any one of them.
Example
Input: 4 0 0 0 0 8 2 0 0 0 4 0 0 0 Output: 2 4 1 3 2 6 1 7 4 8 3 5
n皇后问题,转化为dlx精确覆盖,行列和斜线作为列,不过斜线无需全部覆盖,只是作为约束条件。
转化之前要先剪枝,可以大大减少需要搜索的量.
#include<cstdio> #include<vector> #include<cmath> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const ll maxn = 5005; int T, n, m, x, y, t, X, Y,tot,u[maxn],p[maxn][2],vis[maxn]; inline void read(int &ret) { char c; do { c = getchar(); } while (c < '0' || c > '9'); ret = c - '0'; while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0'); } struct DLX { #define maxn 50005 #define F(i,A,s) for (int i=A[s];i!=s;i=A[i]) int L[maxn], R[maxn], U[maxn], D[maxn]; int row[maxn], col[maxn], ans[maxn], cnt[maxn]; int n, m, num, sz; void add(int now, int l, int r, int u, int d, int x, int y) { L[now] = l; R[now] = r; U[now] = u; D[now] = d; row[now] = x; col[now] = y; } void reset(int n, int m) { num = 0x7FFFFFFF; this->n = n; this->m = m; for (int i = 0; i <= m; i++) { add(i, i - 1, i + 1, i, i, 0, i); cnt[i] = 0; } L[0] = m; R[m] = 0; sz = m + 1; } void insert(int x, int y) { int ft = sz - 1; if (row[ft] != x) { add(sz, sz, sz, U[y], y, x, y); U[D[sz]] = sz; D[U[sz]] = sz; } else { add(sz, ft, R[ft], U[y], y, x, y); R[L[sz]] = sz; L[R[sz]] = sz; U[D[sz]] = sz; D[U[sz]] = sz; } ++cnt[y]; ++sz; } //精确覆盖 void remove(int now) { R[L[now]] = R[now]; L[R[now]] = L[now]; F(i, D, now) F(j, R, i) { D[U[j]] = D[j]; U[D[j]] = U[j]; --cnt[col[j]]; } } void resume(int now) { F(i, U, now) F(j, L, i) { D[U[j]] = j; U[D[j]] = j; ++cnt[col[j]]; } R[L[now]] = now; L[R[now]] = now; } bool dfs(int x) { //if (x + A() >= num) return; if (x==n) { num = min(num, x); return true; } int now = R[0]; if (now>n) return false; for (int i=R[0];i<=n;i=R[i]) if (cnt[now]>cnt[i]) now = i; remove(now); F(i, D, now) { ans[x] = row[i]; F(j, R, i) remove(col[j]); if (dfs(x + 1)) return true; F(j, L, i) resume(col[j]); } resume(now); return false; } //精确覆盖 //重复覆盖 void Remove(int now) { F(i, D, now) { L[R[i]] = L[i]; R[L[i]] = R[i]; } } void Resume(int now) { F(i, U, now) L[R[i]] = R[L[i]] = i; } int vis[maxn]; int flag[maxn]; int A() { int dis = 0; F(i, R, 0) vis[i] = 0; F(i, R, 0) if (!vis[i]) { dis++; vis[i] = 1; F(j, D, i) F(k, R, j) vis[col[k]] = 1; } return dis; } void Dfs(int x) { if (!R[0]) num = min(num, x); else if (x + A()<num) { int now = R[0]; F(i, R, 0) if (cnt[now]>cnt[i]) now = i; F(i, D, now) { Remove(i); F(j, R, i) Remove(j); Dfs(x + 1); F(j, L, i) Resume(j); Resume(i); } } } //重复覆盖 void display(int x) { for (int i=0;i<num;i++) u[p[ans[i]][0]]=p[ans[i]][1]; for (int i=1;i<=x;i++) { printf("%d%s",u[i],i==x?"\n":" "); } } }dlx; void insert(int x,int y,int z) { int a,b,c,d; a=x; b=n+y; c=n+n+x+y-1; d=n+n+n+n-1+(n-x)+y; if (vis[a]+vis[b]+vis[c]+vis[d]) return ; tot++; p[tot][0]=x; p[tot][1]=y; dlx.insert(tot,a); dlx.insert(tot,b); dlx.insert(tot,c); dlx.insert(tot,d); if (z) vis[a]=vis[b]=vis[c]=vis[d]=1; } int main() { //read(T); while (~scanf("%d", &n)) { tot=0; dlx.reset(n,6*n-2); memset(vis,0,sizeof(vis)); for (int i=1;i<=n;i++) { scanf("%d",&x); if (x) insert(i,x,1); } for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) insert(i,j,0); if (dlx.dfs(0)) dlx.display(n); } return 0; }
相关文章推荐
- 通用Key-Value存储系统的存储管理策略解析
- Architecture,Valid architectures,Build Active Architecture Only
- 配置文件读取
- UISearchBar 点击取消回到原来位置时会跳动的解决方法
- Maximum Subarray
- Qt 5.3 下OpenCV 2.4.11 开发(3)简单的GUI项目
- Daikon Forge GUI Library(dfgui)之Scroll Panel
- [UIScreen mainScreen].bounds.size获取设备长宽时的问题
- UILable 设置对齐方式扩展
- 用户选择一个value过滤数据
- 初学miniui之miniui的使用
- easyui获取datagrid所有行、变化行、更新行等数据的方法
- Result Maps collection already contains value for
- UIAlertView,POP返回键盘闪现
- Android学习心得(9) --- ndk-build脚本参数用法
- Easyui 中的placeholder属性
- iOS UIButton按钮图片在上文字在下
- UI 总结-1 UIButton
- iOS UI第一周总结
- priority_queue(优先队列)