DLX hdu3111 hdu 3909 hdu3663 hdu3957

来源:互联网 发布:搬砖网络语言什么意思 编辑:程序博客网 时间:2024/05/19 02:30
//http://sqybi.com/works/dlxcn//*同时有部分覆盖与完全覆盖时,尝试取某一行时,一定要先去掉部分覆盖的列,再去完全覆盖的列。因为去完全覆盖的列时,会把部分覆盖的列的关系打乱,使后面再去部分覆盖时找不到了,无法结束。hdu3957每个角色最多有两个身份,给出每个角色的身份的胜败关系,选出最少的角色的某个身份,使得无论其它角色选择什么身份,至少有一个你选的角色打败它。*/#include<stdio.h>#include<string.h>#include<iostream>using namespace std;const int maxr=55;const int maxc=110;const int maxn=11000;int L[maxn],R[maxn],U[maxn],D[maxn],RH[maxn],CH[maxn],ynum[maxc];int sum,r,c,size,head;bool mat[maxr][maxc],vis[maxc];int AddNode(int l,int r,int u,int d){L[size]=l,R[size]=r,U[size]=u,D[size]=d;L[r]=R[l]=U[d]=D[u]=size;return size++;}void Make(){int i,j,k;memset(ynum,0,sizeof(ynum));size=0;head=AddNode(size,size,size,size);for(i=0;i<c;i++){CH[i+1]=i;AddNode(L[head],head,size,size);}for(i=0;i<r;i++)for(k=-1,j=0;j<c;j++){if(!mat[i][j]) continue;RH[size]=i,CH[size]=j,ynum[j]++;if(k==-1)k=AddNode(size,size,U[j+1],j+1);else k=AddNode(k,R[k],U[j+1],j+1);}for(i=0;i<c;i++)if(!ynum[i])L[R[i+1]]=L[i+1],R[L[i+1]]=R[i+1];}void Remove(int c)//完全覆盖的去除c列元素的行{L[R[c]]=L[c],R[L[c]]=R[c];int i,j,k;for(i=U[c];i!=c;i=U[i])for(j=R[i];j!=i;j=R[j])ynum[CH[j]]--,U[D[j]]=U[j],D[U[j]]=D[j];}void Resume(int c){int i,j,k;for(i=D[c];i!=c;i=D[i])for(j=L[i];j!=i;j=L[j])ynum[CH[j]]++,U[D[j]]=D[U[j]]=j;L[R[c]]=R[L[c]]=c;}void Remove1(int c)//部分覆盖去除c列{int i;for(i=U[c];i!=c;i=U[i])L[R[i]]=L[i],R[L[i]]=R[i];}void Resume1(int c){int i;for(i=D[c];i!=c;i=D[i])L[R[i]]=R[L[i]]=i;}int h(){int i,j,k,num=0;memset(vis,false,sizeof(vis));for(i=R[head];i!=head&&i<=r;i=R[i])if(!vis[CH[i]]){num++;vis[CH[i]]=true;for(j=U[i];j!=i;j=U[j])for(k=R[j];k!=j;k=R[k])vis[CH[k]]=true;}return num;}void DFS(int t){if(t+h()>=sum) return;//部分覆盖的IDA*if(R[head]==head||R[head]>r){if(sum>t) sum=t;return;}int i,j,k;for(k=-1,i=R[head];i!=head&&i<=r;i=R[i])if(k==-1||ynum[CH[i]]<ynum[CH[k]])k=i;//printf("%d %d\n",t,k);for(i=U[k];i!=k;i=U[i]){Remove1(i);//先去掉部分覆盖的for(j=R[i];j!=i;j=R[j])if(CH[j]<r) Remove1(j);for(j=R[i];j!=i;j=R[j])//再去完全覆盖{if(CH[j]>=r) Remove(CH[j]+1);//else Remove1(j); //混着写是错的,无法正常结束}DFS(t+1);for(j=L[i];j!=i;j=L[j]){if(CH[j]>=r) Resume(CH[j]+1);//else Resume1(j);}for(j=L[i];j!=i;j=L[j])if(CH[j]<r) Resume1(j);Resume1(i);}}int main(){int t,test=1,n,i,j,k,kk,u,v;scanf("%d",&t);while(t--){scanf("%d",&n);memset(mat,false,sizeof(mat));for(i=0;i<n;i++){scanf("%d",&k);for(j=0;j<k;j++){if(k==2)mat[i*2+j][i*2+(j^1)]=true;mat[i*2+j][i*2+j]=true;mat[i*2+j][n*2+i]=true;scanf("%d",&kk);while(kk--){scanf("%d%d",&u,&v);mat[i*2+j][u*2+v]=true;}}}r=n*2,c=n*3;Make();sum=r;DFS(0);printf("Case %d: %d\n",test++,sum);}return 0;}
//hdu3111求9*9的数独#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;const int maxr=1100;const int maxc=410;const int maxn=maxr*maxc;int o[maxn],L[maxn],R[maxn],U[maxn],D[maxn],RH[maxn],CH[maxn],ynum[maxc];int size,head,r,c,g[10][10];bool mat[maxr][maxc];int AddNode(int l,int r,int u,int d){L[size]=l,R[size]=r,U[size]=u,D[size]=d;L[r]=R[l]=U[d]=D[u]=size;return size++;}void Remove(int c)//删除c列{L[R[c]]=L[c],R[L[c]]=R[c];int i,j;for(i=U[c];i!=c;i=U[i])for(j=R[i];j!=i;j=R[j])D[U[j]]=D[j],U[D[j]]=U[j];}void Resume(int c)//恢复c列{int i,j;for(i=D[c];i!=c;i=D[i])for(j=L[i];j!=i;j=L[j])D[U[j]]=U[D[j]]=j;L[R[c]]=R[L[c]]=c;}bool DFS(int kk){if(R[head]==head) return true;int i,j,k;for(k=-1,i=R[head];i!=head;i=R[i])//找含最少元素的列if(k==-1||ynum[CH[i]]<ynum[CH[k]])k=i;Remove(k);for(i=U[k];i!=k;i=U[i])//枚举这列元素所在的行{o[kk]=RH[i];for(j=R[i];j!=i;j=R[j])Remove(CH[j]+1);if(DFS(kk+1)) return true;for(j=L[i];j!=i;j=L[j])Resume(CH[j]+1);}Resume(k);return false;}void Make(){int i,j,k;memset(mat,false,sizeof(mat));for(i=0;i<9;i++)for(j=0;j<9;j++)for(k=1;k<=9;k++)if(!g[i][j]||g[i][j]==k){mat[i*9*9+j*9+k-1][i*9+j]=true;mat[i*9*9+j*9+k-1][9*9+i*9+k-1]=true;mat[i*9*9+j*9+k-1][2*9*9+j*9+k-1]=true;mat[i*9*9+j*9+k-1][3*9*9+(i/3*3+j/3)*9+k-1]=true;}r=9*9*9;c=4*9*9;size=0,head=0;memset(ynum,0,sizeof(ynum));AddNode(size,size,size,size);for(i=0;i<c;i++){CH[size]=i;AddNode(L[head],head,size,size);}for(i=0;i<r;i++)for(k=-1,j=0;j<c;j++){if(!mat[i][j]) continue;RH[size]=i,CH[size]=j,ynum[j]++;if(k==-1)k=AddNode(size,size,U[j+1],j+1);else k=AddNode(k,R[k],U[j+1],j+1);}}int main(){int t,i,j;char ch[110];scanf("%d",&t);getchar();while(t--){for(i=0;i<9;i++){gets(ch);for(j=0;j<9;j++){if(ch[j]=='?') g[i][j]=0;else g[i][j]=ch[j]-'0';}}Make();if(!DFS(0))printf("impossible\n");else{sort(o,o+81);for(i=0;i<81;i++){printf("%d",o[i]%9+1);if(i%9==8) printf("\n");}}if(t) {printf("---\n");gets(ch);}}return 0;}