题目要求
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;
}