首页 > 代码库 > ZOJ 3209 Dancing Links
ZOJ 3209 Dancing Links
思路:这题挺好的,本来模板不是自己敲的嘛,理解了Dancing Links后是找了一个模板的,然后正好这题让自己加深理解了,也知道在实际中怎么建矩阵求解了。
把n*m的矩阵看成n*m个格子,像那个数独一样,作为n*m列;每一个矩形一行。
行列都建好矩阵后,就可以用舞蹈链求解了。
问题即转化为从这些行中选择最少的一部分使每一列被覆盖且仅覆盖一次。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<set> #include<cmath> #include<bitset> #define mem(a,b) memset(a,b,sizeof(a)) #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r #define llson j<<1,l,mid #define rrson j<<1|1,mid+1,r #define INF 0x7fffffff #define maxn 1000005 typedef long long ll; typedef unsigned long long ull; using namespace std; int head,sz; int U[maxn],D[maxn],L[maxn],R[maxn];//上下左右链表指针 int H[maxn],ROW[maxn],C[maxn],S[maxn],O[maxn]; 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) { for(int i=U[c]; i!=c; i=U[i]) { for(int j=L[i]; j!=i; j=L[j]) { ++S[C[j]]; U[D[j]]=j; D[U[j]]=j; } } L[R[c]]=c; R[L[c]]=c; } void init(int m)//m是列 { head=0;//头指针为0 for(int i=0; i<=m; i++) { U[i]=i; D[i]=i;//建立双向十字链表 L[i]=i-1; R[i]=i+1; S[i]=0; } R[m]=0; L[0]=m; S[0]=INF+1; sz=m+1; memset(H,0,sizeof(H)); } void insert(int i, int j) { if(H[i]) { L[sz] = L[H[i]]; R[sz] = H[i]; L[R[sz]] = sz; R[L[sz]] = sz; } else { L[sz] = sz; R[sz] = sz; H[i] = sz; } U[sz] = U[j]; D[sz] = j; U[D[sz]] = sz; D[U[sz]] = sz; C[sz] = j; ROW[sz] = i; ++S[j]; ++sz; } int ans; void dfs(int k) { if(R[head]==head) { if(ans>k) ans=k; return; } int s=INF,c; for (int t=R[head]; t!=head; t=R[t]) if (S[t]<s) s=S[t],c=t; remove(c); for(int i=D[c]; i!=c; i=D[i]) { O[k]=ROW[i]; for(int j=R[i]; j!=i; j=R[j]) remove(C[j]); dfs(k+1); for(int j=L[i]; j!=i; j=L[j]) resume(C[j]); } resume(c); } int main() { //freopen("1.txt","r",stdin); int t; cin>>t; while(t--) { int n,m,p,i,j,k,x1,y1,x2,y2; scanf("%d%d%d",&n,&m,&p); init(n*m); for(i=1;i<=p;i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); for(j=x1;j<x2;j++) for(k=y1+1;k<=y2;k++) insert(i,j*m+k); } ans=INF; dfs(0); printf("%d\n",ans==INF?-1:ans); } return 0; }
ZOJ 3209 Dancing Links
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。