Anniversary Cake (深搜)

Anniversary Cake

Problem Description
Nahid Khaleh decides to invite the kids of the “Shahr-e Ghashang” to her wedding anniversary. She wants to prepare a square-shaped chocolate cake with known size. She asks each invited person to determine the size of the piece of cake that he/she wants (which should also be square-shaped). She knows that Mr. Kavoosi would not bear any wasting of the cake. She wants to know whether she can make a square cake with that size that serves everybody exactly with the requested size, and without any waste.

Input
The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by input data for each test case. Each test case consist of a single line containing an integer s, the side of the cake, followed by an integer n (1 ≤ n ≤ 16), the number of cake pieces, followed by n integers (in the range 1…10) specifying the side of each piece.

Output
There should be one output line per test case containing one of the words KHOOOOB! or HUTUTU! depending on whether the cake can be cut into pieces of specified size without any waste or not.

Sample Input
2
4 8 1 1 1 1 1 3 1 1
5 6 3 3 2 1 1 1

Sample Output
KHOOOOB!
HUTUTU!

大致题意:
有一块边长为BoxSize的正方形的大蛋糕,现在给出n块不同尺寸的正方形的小蛋糕的边长,
问是否能把大蛋糕按恰好切割为这n块小蛋糕,要求每块小蛋糕必须为整块。

可以把大蛋糕想象为一个蛋糕盒子,然后往里面装小蛋糕。
装蛋糕时遵循以下原则:
自下而上,自左至右;
即先装好盒子底部,再继续往上层装,且装每一层时都靠左边放蛋糕;
大蛋糕优先装,因为小蛋糕灵活度比较高。

#include<stdio.h>
#include<string.h>

//用排序来确定从大到小的蛋糕,再遍历,超时,用数组确定每个蛋糕大小有多少个
int t,s,n,arr[11];// arr 为各种大小蛋糕的个数!s为”大蛋糕“尺寸,n为“小蛋糕”数量
int col[41];//统计每列已被占用的格子

int dfs(int Num)//Num已放入蛋糕盒子的数量
{
    if(Num == n)
        return 1;
    int min = 50,p = 0;
    //从左寻找格子数被填充最少的列
    for(int i = 0; i<s; i++)
    {
        if(min>col[i])
        {
            min = col[i];
            p = i;//记录哪一列
        }
    }
    for(int size = 10; size>=1; size--)//从大到小的尺寸开始自下而上的放入盒子
    {
        if(!arr[size])//Size 大小的蛋糕个数为 0 的情况
            continue;
        //判断横向和纵向是否越界
        if(s-min >=size && s-p >=size)
        {
            int wide = 0;
            //检查盒子从第prow列到第prow+size-1列,共size列的宽度wide中
            //是否每列剩余的空间都足够放入高度为size的蛋糕
            for(int j = p; j<=p+size-1; j++)
                if(col[j] <= col[p])//判断后面的各列填充数是否满足条件
                {
                    wide++;
                }
            if(wide>=size)
            {
                int k;
                //放入尺寸为Size的蛋糕
                arr[size]--;
                for(k = p; k<=p+size-1; k++)
                {
                    col[k]+=size;
                }
                if(dfs(Num+1))
                    return 1;
                //回溯
                arr[size]++;
                for(k = p; k<=p+size-1; k++)
                {
                    col[k]-=size;
                }
            }
        }
    }
    return 0;
}

int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(col,0,sizeof(col));
        memset(arr,0,sizeof(arr));
        scanf("%d%d",&s,&n);
        int size,k = 0,l = 0;//l 记录 size>(s/2) 的个数
        for(int i = 0; i<n; i++)
        {
            scanf("%d",&size);
            k += size*size;
            arr[size]++;
            if(size>(s/2))
                l++;
        }
        if(l>1 || k != s*s)//如果面积不相等直接输出HUTUTU!
        {
            printf("HUTUTU!\n");
            continue;
        }
        if(dfs(0))
        {
            printf("KHOOOOB!\n");
        }
        else
            printf("HUTUTU!\n");
    }
    return 0;
}

参考:https://blog.csdn.net/lyy289065406/article/details/6683250

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值