POJ 1020 Anniversary Cake(DFS)

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!

Source

Tehran 2002, First Iran Nationwide Internet Programming Contest
 
    题目大致意思:过生日了,又要分蛋糕了,每个人都指定了一块大小的蛋糕,问你能不能做一个蛋糕使得它刚刚好被分完。蛋糕是方形的,指定蛋糕也是方形的。
    分析:
    其实我们可以看作是把那些小蛋糕放到大蛋糕里面,如果刚好放下就OK,不行那就不OK咯。
    都说到这份上了,要用DFS来做都有个底了吧。
    关键是怎么做,一开始我看到这题目虽然知道要用DFS,但是因为这个有两个量,长、宽,然后有点懵,不知道怎么下手,看了别人的代码,突然发现要走的路还长。。。。。。
    废话不多说,其实还是很简单的。
    1.既然有两个量,那就多考虑一下咯
    2.如果我们按照列来放的话,那么我们就要保证所在列的剩余行数一定要小于等于指定蛋糕的边长
    3.假如我们的列的编号是从1开始的,那么我们就要保证当前选定列+指定蛋糕边长-1<=蛋糕的边长 
    4.那么我们放入的列的区间就应该是【i,i+index-1】 /*i是选定的列,index是指定蛋糕边长*/,在这个区间内,不容许出现花销行数大于最小花销的列,因为如果有这种情况,那么蛋糕最后是绝对放不下的,因为这样会出现小空隙或者根本无法放下这个指定蛋糕
    
代码如下:
#include <iostream>

using namespace std;

int pos[100];                      //第i列用了pos[i]行
int cake[18];                      //第i种蛋糕的数量
int cake_num;
int cake_size;

bool DFS(int num)
{
    if (num==cake_num) return true;       //蛋糕都用完了返回true
    int MIN = 999, index = -1;
    for (int i = 1; i <= cake_size; i++)      //找到行数花销最小的列
    {
        if (MIN > pos[i])
        {
            MIN = pos[i];
            index = i;
        }
    }
    for (int i = 10; i >= 1; i--)         //枚举每一条边
    {
        if (cake[i] && i + MIN <= cake_size&&index + i - 1 <= cake_size)     //边界试探
        {
            int flag = 1;
            for (int j = index; j <= i + index - 1; j++)        //枚举后续的列
            {
                if (pos[j] > MIN)           //有花销更大的列 那么就不能放在这里
                {
                    flag = 0;
                    break;
                }
            }
            if (!flag) continue;
            cake[i]--;              //蛋糕可以放下
            for (int j = index; j <= index + i - 1; j++) pos[j] += i;
            if (DFS(num + 1)) return true;
            cake[i]++;            //放错地方了
            for (int j = index; j <= index + i - 1; j++) pos[j] -= i;
        }
    }
    return false;
}

int main()
{
    int t, edge, sum;
    cin >> t;
    while (t--)
    {
        sum = 0;
        memset(pos, 0, sizeof(pos));
        memset(cake, 0, sizeof(cake));
        cin >> cake_size;
        cin >> cake_num;
        for (int i = 1; i <= cake_num; i++)
        {
            cin >> edge;
            cake[edge]++;
            sum += edge*edge;
        }
        if (sum != cake_size*cake_size)
        {
            cout << "HUTUTU!" << endl;
            continue;
        }
        if (DFS(0))
            cout << "KHOOOOB!" << endl;
        else cout << "HUTUTU!" << endl;
    }
}
View Code

 

转载于:https://www.cnblogs.com/LHJL8023/p/8018114.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值