DLX SPOJ 1771 Yet Another N-Queen Problem (八皇后变形)
2014-04-16 20:00
246 查看
需要注意的有:
(1)行和列,斜线的hash
(2)搜的时候只用搜行或列即可
(3)成功条件:d >=n
(4)注意初始化!!!
???为什么白书的模板TLE???
网上模板ac:
白书模板TLE:(???????)
(1)行和列,斜线的hash
(2)搜的时候只用搜行或列即可
(3)成功条件:d >=n
(4)注意初始化!!!
???为什么白书的模板TLE???
网上模板ac:
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxnode = 55 * 55 * 4; const int maxr = 55 * 55; const int maxc = 55 * 6; int U[maxnode],D[maxnode],L[maxnode],R[maxnode],C[maxnode],row[maxnode]; int H[maxr],S[maxc]; int ansd, ans[maxr];/// 注意初始化 int n,sz; void init(int r,int c) { for(int i=0; i<=c; ++i) { S[i]=0; U[i]=D[i]=i; L[i+1]=i; R[i]=i+1; } R[sz=c]=0; while(r)H[r--]=-1; } void remove(int c) { L[R[c]]=L[c],R[L[c]]=R[c]; for(int i=D[c]; i!=c; i=D[i]) for(int j=R[i]; j!=i; j=R[j]) U[D[j]]=U[j],D[U[j]]=D[j],--S[C[j]]; } void resume(int c) { L[R[c]]=R[L[c]]=c; for(int i=U[c]; i!=c; i=U[i]) for(int j=L[i]; j!=i; j=L[j]) ++S[C[U[D[j]]=D[U[j]]=j]]; } bool Dance(int d) { if(d>=n) { ansd = d; return 1; } if(!R[0])return 0; int c,tmp=maxnode; for(int i=R[0]; i; i=R[i]) if(i<=n) { if(S[i]<tmp)tmp=S[c=i]; } else break; remove(c); for(int i=D[c]; i!=c; i=D[i]) { ans[d] = row[i]; for(int j=R[i]; j!=i; j=R[j])remove(C[j]); if(Dance(d+1))return 1; for(int j=L[i]; j!=i; j=L[j])resume(C[j]); } resume(c); return 0; } void Link(int r,int c) { ++S[C[++sz]=c]; row[sz]=r; D[sz]=D[c]; U[D[c]]=sz; U[sz]=c; D[c]=sz; if(H[r]<0)H[r]=L[sz]=R[sz]=sz; else { R[sz]=R[H[r]]; L[R[H[r]]]=sz; L[sz]=H[r]; R[H[r]]=sz; } } void place(int &p1,int &p2,int &p3,int &p4,int i,int j) { p1=j,p2=n+i,p3=n+n+i-j+n,p4=n+n+n+n-1+i+j-1; } bool p[maxnode]; int a[55]; int main() { int i,j,k,p1,p2,p3,p4; while(scanf("%d",&n)!=-1) { for(i=1; i<=n*6-2; ++i)p[i]=0; init(n*n,n*6-2); for(k=i=1; i<=n; ++i) { scanf("%d",&j); if(j) { place(p1,p2,p3,p4,i,j); p[p1]=p[p2]=p[p3]=p[p4]=1; Link((i - 1) * n + j,p1),Link((i - 1) * n + j,p2),Link((i - 1) * n + j,p3),Link((i - 1) * n + j,p4); } } for(i=1; i<=n; ++i) for(j=1; j<=n; ++j) { place(p1,p2,p3,p4,i,j); if(p[p1]||p[p2]||p[p3]||p[p4])continue; Link((i - 1) * n + j,p1),Link((i - 1) * n + j,p2),Link((i - 1) * n + j,p3),Link((i - 1) * n + j,p4); } Dance(0); for (int i = 0; i < ansd; i++) { int val = ans[i]; int x = (--val) / n; int y = val % n; x++; y++; a[x] = y; } for (int i = 1; i <= n; i++) { if (i != 1) printf(" "); printf("%d", a[i]); } puts(""); } return 0; }
白书模板TLE:(???????)
#include <cstdio> #include <iostream> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int maxnode = 55 * 55 * 4; const int maxr = 55 * 55; const int maxc = 55 * 6; int N; ///精确区间覆盖 ///行编号从1开始,列编号为1~c,结点0为表头结点 ///注意给行和列的编号 ///注意sz,ans.要自己初始化和赋值!!! struct DLX { int n , sz; // 每列的行数,节点总数 int S[maxc]; // 各列节点总数 int row[maxnode],col[maxnode]; // 各节点行列编号 int L[maxnode],R[maxnode],U[maxnode],D[maxnode]; // 十字链表 int ansd, ans[maxr]; // 解,行数 void init(int n ) { this->n = n ; for(int i = 0 ; i <= n; i++ ) { U[i] = i ; D[i] = i ; L[i] = i - 1; R[i] = i + 1; } R = 0 ; L[0] = n; sz = n + 1 ; memset(S,0,sizeof(S)); } void addRow(int r,vector<int> c1) { int first = sz; for(int i = 0 ; i < c1.size(); i++ ) { int c = c1[i]; L[sz] = sz - 1 ; R[sz] = sz + 1 ; D[sz] = c ; U[sz] = U[c]; D[U[c]] = sz; U[c] = sz; row[sz] = r; col[sz] = c; S[c] ++ ; sz ++ ; } R[sz - 1] = first ; L[first] = sz - 1; } // 顺着链表A,遍历除s外的其他元素 #define FOR(i,A,s) for(int i = A[s]; i != s ; i = A[i]) void remove(int c) { L[R[c]] = L[c]; R[L[c]] = R[c]; FOR(i,D,c) FOR(j,R,i) { U[D[j]] = U[j]; D[U[j]] = D[j]; --S[col[j]]; } } void restore(int c) { FOR(i,U,c) FOR(j,L,i) { ++S[col[j]]; U[D[j]] = j; D[U[j]] = j; } L[R[c]] = c; R[L[c]] = c; } bool dfs(int d) { if (d >= N) { ansd = d; return true; } if (!R[0]) return false;///!!! // 找S最小的列c int c = R[0], tmp = S[R[0]]; FOR(i, R, 0) if (i <= N) if (S[i] < tmp) tmp = S[c = i];///斜线部分不遍历 else break; remove(c); FOR(i,D,c) { ans[d] = row[i]; FOR(j,R,i) remove(col[j]); if(dfs(d + 1)) return true; FOR(j,L,i) restore(col[j]); } restore(c); return false; } bool solve(vector<int> & v) { v.clear(); if(!dfs(0)) return false; for(int i = 0 ; i< ansd ; i ++ ) v.push_back(ans[i]); return true; } }; DLX solver; void decode(int val, int &x, int &y) { val--; x = val / N; y = val % N; x++; y++; } vector<int>v; bool p[55 * 55 * 4]; void place(int &p1,int &p2,int &p3,int &p4,int i,int j) { p1=j,p2=N+i,p3=N+N+i-j+N,p4=N+N+N+N-1+i+j-1; } int main() { int a[55]; while (cin >> N) { memset(p, 0, sizeof(p)); solver.init(6 * N - 2); for (int i = 1; i <= N; i++) { scanf("%d", &a[i]); if (!a[i]) continue; int p1, p2, p3, p4; place(p1, p2, p3, p4, i, a[i]); v.clear(); v.push_back(p1); v.push_back(p2); v.push_back(p3); v.push_back(p4); p[p1] = p[p2] = p[p3] = p[p4] = 1; solver.addRow((i - 1) * N + a[i], v); } for (int i = 1; i <= N; i++) { for (int j = 1; j <= N; j++) { int p1, p2, p3, p4; place(p1, p2, p3, p4, i, j); if (p[p1] || p[p2] || p[p3] || p[p4]) continue; v.clear(); v.push_back(p1); v.push_back(p2); v.push_back(p3); v.push_back(p4); solver.addRow((i - 1) * N + j, v); } } v.clear(); solver.solve(v); for (int i = 0; i < v.size(); i++) { int x, y; decode(v[i], x, y); a[x] = y; } for (int i = 1; i <= N; i++) { if (i != 1) printf(" "); printf("%d", a[i]); } puts(""); } return 0; }
相关文章推荐
- spoj 1771 Yet Another N-Queen Problem
- Spoj1771-Yet Another N-Queen Problem(精确覆盖)
- SPOJ 1771 Yet Another N-Queen Problem 解题报告(Dancing Link)
- DLX(n皇后)spoj1771
- SPOJ 1771 NQUEEN (DLX解n皇后问题)
- 【SPOJ】1771 Yet Another N-Queen Problem
- SPOJ 1771 Yet Another N-Queen Problem
- Spoj 1771(Dancing Links 精确覆盖变形)
- SPOJ 1771 NQUEEN Yet Another N-Queen Problem
- spoj NQUEEN N皇后 DLX
- GSS3 SPOJ 1716. Can you answer these queries III gss1的变形
- PAT - 甲级 - 1128. N Queens Puzzle (20) (8皇后问题变形)
- SPOJNQUEEN-Yet Another N-Queen Problem
- UVA - 10401 Injured Queen Problem N皇后变形
- DLX(变形数独)hdu4069
- (POJ1321) 棋盘问题 <DFS ,八皇后问题的变形,皇后数目小于等于行数即有些行可以不放>
- poj 1321 棋盘问题 【dfs】【n皇后变形】
- poj1315 变形N皇后
- uva 639 Don't Get Rooked 变形N皇后问题 暴力回溯
- uva 639 Don't Get Rooked 变形N皇后问题 暴力回溯