POJ编程8----Anniversary Cake

POJ编程8----Anniversary Cake

题目要求

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!

算法思路

大体思路是深度优先搜索,遍历所有的小块,对每一块试验每一个位置,看是否可以填满大蛋糕。但如果初始化一个二维矩阵作为蛋糕,标记每一个位置是否被占用,是肯定会超时的。

较好的思路是只用一个一维数组d[41],标记每一竖列目前填充到的行的序号。填充的顺序按照从上到下,从左到右,每次优先填充d[]最小的值对应的那列,即最少的那列,在凹陷处填充的块从大往小尝试,如果已经无法填充这个空隙,那这个分支pass掉,回到上一层,尝试其他操作。

参考:https://www.cnblogs.com/dengeven/p/3228146.html

示例代码

注释比较清楚啦~

#include <iostream>
using namespace std;

int s, n;//蛋糕总边长,分的块数
int c[11];//十种长度的边长分别对应的数量
int d[41];//蛋糕

int sum;
bool ok;

void reset() {
    memset(c, 0, sizeof(c));
    for (int i = 0; i < 41; ++i) {
        d[i] = 1;
    }
    sum = 0;
    ok = false;
}

void dfs(int a) {//a为目前已经分好的块数
    if (a == n) {
        ok = true;
        exit;
    }
    int i, j;
    int row, clo;
    bool f;
    for (i = 1, clo = 41; i <= s; ++i) {
        if (d[i] < clo) {
            clo = d[i];
            row = i;//找到最小行号对应的列号
        }
    }
    for (i = 10; i > 0; --i) {//从大往小试
        if (c[i] > 0 && row + i - 1 <= s && clo + i - 1 <= s) {
            for (j = row, f = true; j <= row + i - 1; ++j) {
                if (d[j] > clo) {
                    f = false;
                    break;
                }//判断凹陷宽度是否够放下边长为i的块
            }
            if (f) {
                for (j = row; j <= row + i - 1; ++j) {
                    d[j] += i;
                }
                --c[i];
                dfs(a + 1);
                ++c[i];
                for (j = row; j <= row + i - 1; ++j) {
                    d[j] -= i;
                }
            }
        }
    }
}

int main(void) {
    int nCase;
    cin >> nCase;
    for (int caseNo = 1; caseNo <= nCase; ++caseNo) {
        reset();
        cin >> s >> n;
        for (int i = 1; i <= n; ++i) {
            int t;
            cin >> t;
            ++c[t];//记录每种长度的数量
            sum += t * t;
        }
        if (sum != s * s) {
            cout << "HUTUTU!" << endl;
            continue;
        }
        dfs(0);
        if (ok) {
            cout << "KHOOOOB!" << endl;
        }
        else {
            cout << "HUTUTU!" << endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值