背景 Background
笨笨:哼哼哼……今天要干点坏事~
路人甲:0o。(-. - )
笨笨:哈哈哈……看我怎么干坏事吧~(炸弹已安置)
路人甲:啊?!什么什么?你刚刚说什么?
笨笨:切,不理你了……闪人……
描述 Description
现在笨笨有多个正方形的区域要炸——用那经典的按密码的小方块……在这些区域中原有多个引爆点,但是这些引爆点只能引爆所在的一个方形区域(区域大小不限,具体看样例),并且不能和另一个引爆点同时引爆同一个区域。笨笨想知道,在所有的正方形区域中,有哪些是可以一次炸完的。
输入格式 Input Format
输入第一行是正方形区域的个数,为了不太累,个数在50个以内。
然后是对这些正方形区域的描述,各个描述格式如下:
第一行两个数L(0<L<25),N(N>0)。L表示正方形区域的边长,N表示该正方形区域内引爆点个数。
接下来N行每行两个数X,Y(0<x,y<=L)表示在横坐标X,纵坐标Y的地方有一个引爆点。
输出格式 Output Format
对于每一个正方形区域,输出一个"Yes"或一个"No",表示能否一次引爆这个区域。
对于每个正方形区域输出一行。
样例输入 Sample Input
1
5 8
2 4
3 3
3 4
3 5
4 2
4 4
4 5
5 5
样例输出 Sample Output
Yes
时间限制 Time Limitation
1s
对于样例:
引爆点分布图
+-----+
|.....|
|...*.|
|..***|
|.*.**|
|....*|
+-----+
区域分割图
+-----+
|11122|
|11122|
|11134|
|55667|
|55668|
+-----+
在这样的分割下,这个正方形区域可以被一次引爆。
分析:
dfs搜索题。
1.如果这个框中,没有炸弹,那么继续拉大正方形框。
2.如果这个框中有一个炸弹,那就可以递归了,当做这个框里的格子全被这个炸弹炸掉了。
3.如果这个正方形框里有多于一个炸弹,或者这个正方形框里的某些格子以前已经被标记过了(这个地方只要判断一个格子就可以了,程序中我会做标注),那就无解回溯(记得要把这次搜索的标记改回来)
【参考程序】:
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
int a[30][30];
bool no[30][30];
bool ok;
int N,L;
void Init()
{
scanf("%d%d",&L,&N);
memset(a,0,sizeof(a));
int x,y;
for (int i=1;i<=N;i++)
{
scanf("%d%d",&x,&y);
a[x][y]=1;
}
for (int i=1;i<=L;i++)
for (int j=1;j<=L;j++)
a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
}
void dfs(int x,int y)
{
if (ok) return ;
if (x>L)
{
ok=true; return ;
}
int o,k,m; bool check;
if (no[x][y])
{
if (y>=L) dfs(x+1,1);
else dfs(x,y+1);
}
else
{
check=true;
o=L-x+1;
if (L-y+1<o) o=L-y+1;
for (int p=1;p<=o;p++)
{
if (no[x][y+p-1])
{
check=false; k=p;
break;
}
m=a[x+p-1][y+p-1]-a[x+p-1][y-1]-a[x-1][y+p-1]+a[x-1][y-1];
if (m>1)
{
check=false; k=p;
break;
}
else
{
for (int i=x;i<=x+p-1;i++)
no[i][y+p-1]=true;
for (int i=y;i<=y+p-2;i++)
no[x+p-1][i]=true;
if (m==1)
{
if (y+p>L) dfs(x+1,1);
else dfs(x,y+p);
}
if (ok) return ;
}
}
if (!check) k--;
else k=o;
for (int i=x;i<=x+k-1;i++)
for (int j=y;j<=y+k-1;j++)
no[i][j]=false;
}
}
int main()
{
int test;
scanf("%d",&test);
while (test)
{
Init();
memset(no,false,sizeof(no));
ok=false;
dfs(1,1);
if (!ok) printf("No\n");
else printf("Yes\n");
test--;
}
return 0;
}