Problem Description
一个边长为L的正方形可以分成 L*L个小正方形. 有N个石子放在 N个小正方形里,能否将它分成 N个 正方形,使得每个正方形里恰有一个石子且这N 个正方形恰好构成整个正方形 .
Input
输入数据首先包含一个整数T,表示测试实例的个数,然后是T组数据,每组第一行包含2个整数L,N,接下来有N行每行2个整数 r,c,表示第r行c列的小正方形里有一个石子 .1<L<=20;1<N<=L*L; 1<=r,c<=L.
Output
对于每个测试实例,如能将它分成 N个 正方形输出YES, 否则输出 NO
Sample Input
3
5 8
2 4
3 3
3 4
3 5
4 2
4 4
4 5
5 5
3 2
1 1
3 3
2 4
1 1
1 2
2 1
2 2
Sample Output
YES
NO
YES
没什么好说的,直接暴力的枚举每个正方形大小盖上去。
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int sz=25;
int T,n,m,x,y,s;
int c[sz][sz];
bool f[sz][sz];
bool check(int x,int y,int r)
{
return c[x+r][y+r]-c[x+r][y-1]-c[x-1][y+r]+c[x-1][y-1]==1;
}
bool dfs()
{
if (!s) return true;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
if (f[i][j])
{
for (int k=0;i+k<=n&&j+k<=n;k++)
{
if (check(i,j,k))
{
s-=k*k;
for (int r=0;r<=k;r++)
{
for (int w=0;w<=k;w++)
{
f[i+r][j+w]=false;
}
}
if (dfs()) return true;
s+=k*k;
for (int r=0;r<=k;r++)
{
for (int w=0;w<=k;w++)
{
f[i+r][j+w]=true;
}
}
}
}
return false;
}
}
}
}
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
s=n*n;
memset(c,0,sizeof(c));
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
c[x][y]=1;
}
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
c[i][j]+=c[i-1][j]+c[i][j-1]-c[i-1][j-1];
f[i][j]=true;
}
}
printf("%s\n",dfs()?"YES":"NO");
}
return 0;
}