首页 > 其他 > 详细

poj 1084 Square Destroyer dlx解重复覆盖

时间:2015-05-02 23:24:47      阅读:293      评论:0      收藏:0      [点我收藏+]

分析:

将问题转化为重复覆盖问题,DancingLink解决。

代码:

//poj 1084
//sep9
#include <iostream>
using namespace std;
const int maxN=10024;
const int maxL=128;
int L[maxN],R[maxN],U[maxN],D[maxN];
int C[maxN],H[maxN];
int S[maxN],A[maxN],X[maxN];
bool makeup[maxL][maxL];
int cnt,ans;
void build(int r,int c)
{
	for(int i=0;i<=c;++i){
		U[i]=D[i]=i;
		L[i]=i==0?c:i-1;
		R[i]=(i+1)%(c+1);
		C[i]=i;//colum head's id
		S[i]=0;
	}
	for(int i=1;i<=r;++i)
		H[i]=-1;//row head's id;	
	cnt=c;
}

void init(int n)
{
	memset(makeup,false,sizeof(makeup));
	int c=1;
	for(int len=1;len<=n;++len)
		for(int i=1;i+len<=n+1;++i)
			for(int j=1;j+len<=n+1;++j){
				for(int k=0;k<len;++k){
					makeup[(i-1)*(2*n+1)+j+k][c]=true;					
					makeup[(i-1+len)*(2*n+1)+j+k][c]=true;
					makeup[i*n+(i-1)*(n+1)+j+k*(2*n+1)][c]=true;
					makeup[i*n+(i-1)*(n+1)+j+k*(2*n+1)+len][c]=true;
				}	
				c++;
			}
}

void link(int r,int c)
{
	++cnt;
	C[cnt]=c;
	++S[c];	
	X[cnt]=r;
	D[cnt]=D[c];
	U[D[c]]=cnt;
	D[c]=cnt;
	U[cnt]=c;
	if(H[r]<0)
		H[r]=L[cnt]=R[cnt]=cnt;
	else{
		R[cnt]=R[H[r]];
		L[cnt]=H[r];
		L[R[H[r]]]=cnt;
		R[H[r]]=cnt;
	}
}

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=D[c];i!=c;i=D[i]){
		L[R[i]]=i;
		R[L[i]]=i;
	}	
}

int get_H()
{
	bool has[maxL];
	memset(has,false,sizeof(has));
	int res=0;
	for(int i=R[0];i!=0;i=R[i])
		if(!has[i]){
			++res;
			for(int j=D[i];j!=i;j=D[j])
				for(int k=R[j];k!=j;k=R[k])
					has[C[k]]=true;
		}	
	return res;
}

void dfs(int k)
{
	if(R[0]==0){
		ans=min(ans,k);
		return ;
	}
	else if(k+get_H()>=ans)
		return ;
	int c=R[0];
	for(int t=R[0],maxx=INT_MAX;t!=0;t=R[t])
		if(S[t]<maxx)
			maxx=S[t],c=t;					
	for(int i=D[c];i!=c;i=D[i]){
		remove(i);
		for(int j=R[i];j!=i;j=R[j]){
			remove(j);
			--S[C[j]];
		}
		dfs(k+1);
		for(int j=L[i];j!=i;j=L[j]){
			resume(j);
			++S[C[j]];
		}
		resume(i);			
	}		
}

int main()
{
	int cases,n,row,col;
	scanf("%d",&cases);
	while(cases--){
		scanf("%d",&n);	
		col=0,row=2*n*(n+1);
		for(int i=1;i<=n;++i)
			col+=i*i;
		build(row,col);
		init(n);
		int num;
		scanf("%d",&num);
		bool vis[maxL];//mark square have been destoryed
		memset(vis,false,sizeof(vis));
		while(num--){
			int r;
			scanf("%d",&r);
			for(int j=1;j<=col;++j)
				if(makeup[r][j]&&!vis[j]){
					vis[j]=true;
					R[L[j]]=R[j];
					L[R[j]]=L[j];
				}				
		}
		for(int i=1;i<=row;++i)
			for(int j=1;j<=col;++j)
				if(makeup[i][j]&&!vis[j])
					link(i,j);
		ans=INT_MAX;
		dfs(0);
		printf("%d\n",ans);
	}
	return 0;	
} 


poj 1084 Square Destroyer dlx解重复覆盖

原文:http://blog.csdn.net/sepnine/article/details/45443227

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!