题解 UVA1603 【Square Destroyer】 题目链接:Link Solution

题解 UVA1603 【Square Destroyer】
题目链接:Link
Solution

Solution

废话不说,先贴代码.....

#include<cstdio>
#include<cstring>
int n,m,maxd,cnt,sum;
int FullSize[625],Size[625];
bool sti[65],in[625][65];
inline int getc(int r,int c)// |  竖线
{
	return r*(2*n+1)+c+n+1;
}
inline int getr(int r,int c)//--   横线
{
	return r*(2*n+1)+c+1;
}
inline int FindNext()//找到下一个没有破坏的正方形
{
	for(int i=1;i<=cnt;i++)
		if(Size[i]==FullSize[i])
			return i;
	return 0;
}
void dfs(int d)//深搜
{
	if(d>=maxd) return;//最优性剪枝
	int next=FindNext();
	if(next==0)
	{
		maxd=d;
		return;
	}
	for(int i=1;i<=sum;i++)
		if(in[next][i])
		{
			for(int j=1;j<=cnt;j++)//删掉火柴棍
				if(in[j][i]) Size[j]--;
			dfs(d+1);
			for(int j=1;j<=cnt;j++)//复原
				if(in[j][i]) Size[j]++;
		}
}
int main()
{
#ifdef local
	freopen("pro.in","r",stdin);
#endif
	int kase;
	scanf("%d",&kase);
	while(kase-->0)
	{
		memset(in,0,sizeof(in));
		memset(sti,1,sizeof(sti));
		cnt=0;
		scanf("%d%d",&n,&m);
		int a,b,e,f;
		for(int i=0;i<m;i++)
		{
			scanf("%d",&a);
			sti[a]=0;
		}
        //状态压缩+预处理
		for(int len=1;len<=n;len++)
			for(int r=0;r+len<=n;r++)
				for(int c=0;c+len<=n;c++)
				{
					cnt++;
					FullSize[cnt]=len*4;
					Size[cnt]=0;
					for(int i=0;i<len;i++)
					{
						a=getr(r,c+i);
						b=getr(r+len,c+i);
						e=getc(r+i,c);
						f=getc(r+i,c+len);
						in[cnt][a]=true;
						in[cnt][b]=true;
						in[cnt][e]=true;
						in[cnt][f]=true;
						Size[cnt]+=sti[a]+sti[b]+sti[e]+sti[f];
					}
				}
		maxd=n*n;//设置上限
		sum=2*n*(n+1);
		dfs(0);
		printf("%d
",maxd);
	}
	return 0;
}