zoj1411_anniversary_dfs

// zoj1411_Anniversary_AC.cpp : Defines the entry point for the console application.
// 题意中的side是边长的意思,square-shape是正方形的意思,题意就是问是否把边长为s的正方形大蛋糕正好切成n块正方形小蛋糕
// 思路:把所有的蛋糕都看成是由边长为1的小蛋糕组成的,然后深搜

#include "stdafx.h"
#include<iostream>
#include<string.h>
#include<vector>
using namespace std;

//每一个请求者的信息
struct rq{
    int size;//请求的蛋糕的边长
    bool isget;//该请求者的要求是否已得到满足
};

vector<rq> rqs;//请求者数组
bool cake[41][41];//蛋糕

//是否可以为当前请求分配蛋糕,index:当前位置,s:大蛋糕的边长,请求分配的小蛋糕的边长
bool canget(int index, int s, int rs)
{
    int x = index / s;
    int y = index%s;
    for (int i = x; i < x + rs; i++)
        for (int j = y; j < y + rs; j++)
            if (!cake[i][j])
                return false;
    return true;
}

//为当前请求分配蛋糕,index:当前位置,s:大蛋糕的边长,请求分配的小蛋糕的边长
void getcake(int index, int s, int rs)
{
    int x = index / s;
    int y = index%s;
    for (int i = x; i < x + rs; i++)
        for (int j = y; j < y + rs; j++)
            cake[i][j] = false;
}

//撤销之前分配的蛋糕,index:当前位置,s:大蛋糕的边长,之前请求分配的小蛋糕的边长
void retcake(int index, int s, int rs)
{
    int x = index / s;
    int y = index%s;
    for (int i = x; i < x + rs; i++)
        for (int j = y; j < y + rs; j++)
            cake[i][j] = true;
}

//深搜
bool dfs(int index, int s)
{
    bool as = true;//allserve:所有请求都已经满足
    for (int i = 0; i < rqs.size(); i++)//判断是否所有请求都已经满足
    {
        if (!rqs[i].isget)
        {
            as = false;
            break;
        }
    }
    if (as)
        return true;
    else//还有请求没有得到满足
    {
        for (int j = index; j < s*s; j++)//查找下一个可以分配的位置
        {
            int x = j / s;
            int y = j%s;
            if (cake[x][y])//当前位置可以分配蛋糕
            {
                bool cansuit[11];//当前位置是否可以为请求分配边长为i的小蛋糕(1<=i<=10),为了避免相同的请求值重复地进行递归查询
                memset(cansuit, true, sizeof(cansuit));
                for (int i = 0; i < rqs.size(); i++)//查找还没有得到满足的请求
                    if ((rqs[i].isget == false) && canget(j, s, rqs[i].size) && cansuit[rqs[i].size])
                    {
                        getcake(j, s, rqs[i].size);//分配蛋糕
                        rqs[i].isget = true;
                        if (dfs((j + rqs[i].size), s))//下一层递归查询,如果返回true则说明当前的分配是正确的,如果返回false说明当前的分配是错误的,说明之前的分配存在问题,要返回上一层重新分配(如果最终是可以满足所有分配的,则每一次递归都是有请求是可以满足的)
                            return true;
                        rqs[i].isget = false;
                        retcake(j, s, rqs[i].size);//回收分配的蛋糕
                        cansuit[rqs[i].size] = false;//在当前位置,当前的请求值(请求分配的蛋糕的边长)是不可以满足最终的分配要求的,所以设置为false,避免后续请求中相同的请求值重复查询
                    }
                return false;//当前位置不可以(为剩余的还没有满足的蛋糕分配请求)分配蛋糕,说明之前的分配存在问题(假设最终是可以满足说有分配条件的,如果不满足则很明显所有的分配都是存在问题)
            }
        }
        return false;//找不到合适的下一个分配位置
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int t;
    cin >> t;
    for (int i = 0; i < t; i++)
    {
        int s, n;
        cin >> s >> n;
        int tsum = 0;
        rqs.clear();
        for (int j = 0; j < n; j++)
        {
            rq trq;
            cin >> trq.size;
            trq.isget = false;
            rqs.push_back(trq);
            tsum += trq.size*trq.size;
        }
        if (tsum != s*s)//如果左右两边不等大很明显就是错误的
            cout << "HUTUTU!" << endl;
        else
        {
            memset(cake, false, sizeof(cake));
            for (int j = 0; j < s; j++)
                for (int k = 0; k < s; k++)
                    cake[j][k] = true;
            if (dfs(0, s))
                cout << "KHOOOOB!" << endl;
            else
                cout << "HUTUTU!" << endl;
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值