UVALive 2659+HUST 1017+ZOJ 3209+FZU 1686 (DLX
UVALive 2659
题目:16*16的数独.试了一发大白模板.
/* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-6) #define IINF (1<<29) #define LINF (1ll<<59) #define INF (1000000000) #define FINF (1e3) typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<ll,ll> P; const int maxr = 5000; const int maxn = 2000; const int maxnode = 20000; struct DLX { int n, sz; int S[maxn]; 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[n] = 0; L[0] = n; sz = n + 1; memset(S, 0, sizeof(S)); } void addRow(int r, vector<int> &columns) { int first = sz; for(int i = 0; i < columns.size(); i++) { int c = columns[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; } #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 (R[0] == 0) { ansd = d; return true; } int c = R[0]; FOR(i,R,0) if(S[i] < S[c]) c = i; 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; } }solver; const int SLOT=0; const int ROW=1; const int COL=2; const int SUB=3; int encode(int a,int b,int c){ return a*256+b*16+c+1; } char puzzal[20][20]; void decode(vector<int> &ans){ for(int i=0;i<ans.size();i++){ ans[i]--; int c=ans[i]%16;ans[i]/=16; int b=ans[i]%16;ans[i]/=16; int a=ans[i]; puzzal[a][b]='A'+c; } } bool flag=0; int main(){ freopen("/home/files/CppFiles/in","r",stdin); //freopen("test.in","r",stdin); //freopen("test.out","w",stdout); while(scanf("%s",puzzal[0])!=EOF){ for(int i=1;i<16;i++){ scanf("%s",puzzal[i]); } if(flag){ puts(""); }else{ flag=1; } solver.init(1024); for(int r=0;r<16;r++){ for(int c=0;c<16;c++){ for(int v=0;v<16;v++){ if(puzzal[r][c]=='-'||puzzal[r][c]=='A'+v){ vector<int> columns; columns.pb(encode(SLOT,r,c)); columns.pb(encode(ROW,r,v)); columns.pb(encode(COL,c,v)); columns.pb(encode(SUB,r/4*4+c/4,v)); solver.addRow(encode(r,c,v),columns); } } } } vector<int> ans; solver.solve(ans); decode(ans); for(int i=0;i<16;i++){ for(int j=0;j<16;j++){ printf("%c",puzzal[i][j]); } puts(""); } } return 0; }
HUST 1017
题目:裸精确覆盖,继续套模板.
/* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-6) #define IINF (1<<29) #define LINF (1ll<<59) #define INF (1000000000) #define FINF (1e3) typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<ll,ll> P; const int maxr = 5000; const int maxn = 2000; const int maxnode = 1e6+3000; struct DLX { int n, sz; int S[maxn]; 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[n] = 0; L[0] = n; sz = n + 1; memset(S, 0, sizeof(S)); } void addRow(int r, vector<int> &columns) { int first = sz; for(int i = 0; i < columns.size(); i++) { int c = columns[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; } #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 (R[0] == 0) { ansd = d; return true; } int c = R[0]; FOR(i,R,0) if(S[i] < S[c]) c = i; 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; } }solver; int n,m; vector<int> columns; vector<int> ans; int main(){ freopen("/home/files/CppFiles/in","r",stdin); //freopen("test.in","r",stdin); //freopen("test.out","w",stdout); while(cin>>n>>m){ solver.init(m); for(int r=1;r<=n;r++){ columns.clear(); int x; scanf("%d",&x); for(int j=0;j<x;j++){ int v; scanf("%d",&v); columns.pb(v); } solver.addRow(r,columns); } ans.clear(); bool f=solver.solve(ans); if(!f){ puts("NO"); continue; } printf("%d",(int)ans.size()); for(int i=0;i<ans.size();i++){ printf(" %d",ans[i]); } puts(""); } return 0; }
题目:给出一张地图的若干个碎片,要求用最少的碎片恢复原地图.
思路:基本还是裸的dlx,搜的时候剪枝一下就好.
/* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-6) #define IINF (1<<29) #define LINF (1ll<<59) #define INF (1000000000) #define FINF (1e3) typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<ll,ll> P; const int maxr = 5000; const int maxn = 2000; const int maxnode = 1e6+3000; struct DLX { int n, sz; int S[maxn]; 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[n] = 0; L[0] = n; sz = n + 1; memset(S, 0, sizeof(S)); } void addRow(int r, vector<int> &columns) { int first = sz; for(int i = 0; i < columns.size(); i++) { int c = columns[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; } #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; } void dfs(int d) { if(ansd!=-1&&d>ansd) return; if (R[0] == 0) { if(ansd==-1) ansd = d; else ansd=min(ansd,d); return; } int c = R[0]; FOR(i,R,0) if(S[i] < S[c]) c = i; remove(c); FOR(i,D,c) { ans[d] = row[i]; FOR(j,R,i) remove(col[j]); dfs(d+1); FOR(j,L,i) restore(col[j]); } restore(c); return; } void solve(vector<int>& v) { v.clear(); dfs(0); for(int i = 0; i < ansd; i++) v.push_back(ans[i]); } }solver; int T,n,m,p; vector<int> columns; int main(){ freopen("/home/files/CppFiles/in","r",stdin); //freopen("test.in","r",stdin); //freopen("test.out","w",stdout); cin>>T; while(T--){ cin>>n>>m>>p; solver.init(n*m); for(int r=1;r<=p;r++){ int x1,y1,x2,y2; columns.clear(); scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x1++,y1++; for(int i=x1;i<=x2;i++){ for(int j=y1;j<=y2;j++){ columns.pb((i-1)*m+j); } } solver.addRow(r,columns); } solver.ansd=-1; solver.dfs(0); printf("%d\n",solver.ansd); } return 0; }
题目;每次可以攻击一个矩形子矩阵,问最少攻击多少次达到目标.
思路:可重复覆盖的DLX和精确覆盖版的主要有这么几个区别
1)删除的时候,精确覆盖要求删去所有当前行已经覆盖的列,以及在已覆盖列上还有元素的所有行,而可重复覆盖只是删除已经覆盖的所有列.
2)由于可重复覆盖通常要求解最小步数,所以需要一个剪枝.
/* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-6) #define IINF (1<<29) #define LINF (1ll<<59) //#define INF (1000000000) #define FINF (1e3) typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<ll,ll> P; const int MaxM = 15*15+10;//width const int MaxN = 15*15+10;//hight const int maxnode = MaxN * MaxM; const int INF = 0x3f3f3f3f; struct DLX{ int n,m,size; int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode]; int H[MaxN],S[MaxM]; int ansd; void init(int _n,int _m){ n = _n; m = _m; for(int i = 0;i <= m;i++){ S[i] = 0; U[i] = D[i] = i; L[i] = i-1; R[i] = i+1; } R[m] = 0; L[0] = m; size = m; for(int i = 1;i <= n;i++) H[i] = -1; } void Link(int r,int c){ ++S[Col[++size]=c]; Row[size] = r; D[size] = D[c]; U[D[c]] = size; U[size] = c; D[c] = size; if(H[r] < 0)H[r] = L[size] = R[size] = size; else{ R[size] = R[H[r]]; L[R[H[r]]] = size; L[size] = H[r]; R[H[r]] = size; } } void remove(int c){ for(int i = D[c];i != c;i = D[i]) L[R[i]] = L[i], R[L[i]] = R[i]; } void resume(int c){ for(int i = U[c];i != c;i = U[i]) L[R[i]] = R[L[i]] = i; } bool v[MaxM]; int f(){ int ret = 0; for(int c = R[0]; c != 0;c = R[c]) v[c] = true; for(int c = R[0]; c != 0;c = R[c]){ if(v[c]){ ret++; v[c] = false; for(int i = D[c];i != c;i = D[i]){ for(int j = R[i];j != i;j = R[j]) v[Col[j]] = false; } } } return ret; } void Dance(int d=0){ if(d + f() >= ansd)return; if(R[0] == 0){ if(d < ansd)ansd = d; return; } int c = R[0]; for(int i = R[0];i != 0;i = R[i]){ if(S[i] < S[c]) c = i; } for(int i = D[c];i != c;i = D[i]){ remove(i); for(int j = R[i];j != i;j = R[j])remove(j); Dance(d+1); for(int j = L[i];j != i;j = L[j])resume(j); resume(i); } } }dan; int n,m; int grid[20][20]; int id[20][20]; int main(){ freopen("/home/files/CppFiles/in","r",stdin); //freopen("test.in","r",stdin); //freopen("test.out","w",stdout); while(cin>>n>>m){ int sz=1; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ scanf("%d",&grid[i][j]); if(grid[i][j]) id[i][j]=sz++; } } dan.init(n*m,sz-1); int n1,m1; scanf("%d%d",&n1,&m1); sz=1; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ for(int x=0;x<n1;x++){ for(int y=0;y<m1;y++){ if(i+x<n&&j+y<m&&grid[i+x][j+y]){ dan.Link(sz,id[i+x][j+y]); } } } sz++; } } dan.ansd=INF; dan.Dance(); printf("%d\n",dan.ansd); } return 0; }