[dfs] Delicious cakes 中等难度的搜索

Problem B Delicious cakes
Time Limit: 1000ms, Memory Limit:64MB
Description
Laura is good at cooking cakes. The delicious and funny cake she cooked is square all the time.
For example, the cake in Picture 1 is square. And you can find it consist of 5*5
这里写图片描述
Picture 1
这里写图片描述
Picture 2
Small blocks of the same size 1*1, the asterisks represent the strawberry Laura put in the cake.
Now, problem comes up. You have to decide whether she can divide the cake into small square pieces that each small piece has exactly one strawberry.
A feasible division for above example was given in Picture 2.

Input
The first line of input is positive integer. It is the number of test cases followed.
The first line of each test contains two integers L(0 < L < 20) and N(N > 0). It represents that the cakes contains L*L blocks and N strawberry. After that, N lines followed. Each line contains two integers xi and yi. It means that there is a strawberry in the block (xi,yi).Assume that Laura would not put no more than one strawberry on the block. There may be one or serveral spaces between these integers.
Output
Print “YES” if you can find a feasible division, otherwise print “NO”.

Sample input:
1
5 8
2 5
3 3
3 4
3 5
4 2
4 4
4 5
5 5
Sample output:
YES

典型的搜索题。从左到右,从上到下进行搜索。
tot[x][y]表示 (1,1)到(x,y)里面草莓的个数,n的平方复杂度预处理。
bool dfs(x,y)
{
由x,y向后找到第一个没有被切下来的方格(tx,ty)
如果全部被切下,返回真
枚举k
{
计算方块中的草莓树n
if(n > 1) break;
if(n == 1)
{
标记整个方块的小正方形
if(dfs(x,y +1)) return 1;
恢复标志
}
}
return 0;
}

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include<cstring>
using namespace std;
const int maxn = 200;
int tot[maxn][maxn],n,k;//tot[x][y] 表示从1,1到x,y里面草莓的个数
bool isin[maxn][maxn]; //isin[x][y] 表示 x,y这个位置是否切掉了
bool dfs(int x,int y)
{
    while(true)
    {
        if(y > n)  { x ++,y = 1; }
        if(x > n)  return true; //如果草莓全部都被切下来了,返回真

        if(!isin[x][y])  break;
        else y++;
    }// isin表示这个位置是否被切掉了
    // 从左往右,从上往下搜索下一个没有被切掉的位置。
    int tx,ty,nodes;
    for(int k = 1; ;k ++)
    {    //从 1 * 1 方块开始,依次放大
        tx = x + k - 1;  ty = y + k - 1;
        //tx,ty为这次想要切的蛋糕的规模
        if(tx > n || ty > n) break;
        //把四块范围内的草莓的个数进行统计。
        nodes = tot[tx][ty] - tot[tx][y-1] - tot[x-1][ty] + tot[x-1][y-1];
        //就是说,他往外扩展的时候,刚好能扩展到第一个可以切到草莓的位置。

        //计算方块中的草莓数量n
        if(nodes > 1) break; //如果草莓个数大于1,那就不用切了 整个dfs失效
        if(nodes == 1) //如果草莓个数刚好等于1
        {
            for(int i = x; i < x + k; i++)
                for(int j = y; j < y + k; j++)
                    isin[i][j] = true;          //把整个方块的小正方形标记一下,已经切掉
            if(dfs(x,y+1))  return true;
            for(int i = x ; i < x + k;i ++)
                for(int j = y;j < y + k;j ++)
                    isin[i][j] = false;          //恢复该标志
        }
    }
    return false;
}

int main()
{
    int t,x,y;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        memset(tot,0,sizeof(tot));
        for(int i = 0 ;i < k;i++)
        {
            scanf("%d%d",&x,&y);
            tot[x][y] = 1;
        }
        for(int i = 1 ;i <= n;i++)
            for(int j = 1; j <= n;j ++)
                tot[i][j] = tot[i-1][j] + tot[i][j-1] - tot[i-1][j-1] + tot[i][j];

        memset(isin,false,sizeof(isin));
        puts(dfs(1,1)? "YES":"NO");
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值