题目大意
给定尺寸的正方形蛋糕进行切割成n份,每份给定尺寸,判断有无剩余。
输入格式
第一行为样例个数t(1≤t≤10)。每个样例为一行,第一个数字为蛋糕尺寸s,第二个数字为将要分成的个数n(1≤n≤16),接下来n个数字为每份的尺寸,尺寸大小为从1到10。
输出格式
若无浪费,输出KHOOOOB!,否则输出HUTUTU!。
样例输入
2 4 8 1 1 1 1 1 3 1 1 5 6 3 3 2 1 1 1
样例输出
KHOOOOB! HUTUTU!
解题思路
若所有份的尺寸和与蛋糕尺寸相同则使用dfs,使用len数组记录蛋糕每一列已分配的大小。
每次分配时从左开始找到len中最小的即可分的蛋糕中面积最大的列,并找到这块面积的边界即最右列,判断从最小列到边界的距离是否够当前需要分配的尺寸;并判断在列数够的前提下通过len数组大小判断剩余行数是否够分配,若够,分配(即更改len数组的值作为已分配),dfs下一块需分配的蛋糕
全部代码
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 6 int size_cake, n; 7 const int maxn = 40; 8 int len[maxn + 5], cnt[maxn + 5]; 9 bool ok; 10 void dfs(int index) 11 { 12 if (ok) return; 13 if (index == n) { 14 ok = 1; 15 return; 16 } 17 int min_col = 1; 18 for (int i = min_col + 1; i <= size_cake; i++) { 19 if (len[i] < len[min_col]) 20 min_col = i; 21 } 22 int border = size_cake + 1; 23 for (int i = min_col + 1; i <= size_cake; i++) { 24 if (len[i] != len[min_col]) { 25 border = i; 26 break; 27 } 28 } 29 for (int i = 10; i >= 1; i--) { 30 if (cnt[i]) { 31 if (i + len[min_col] <= size_cake && i + min_col <= border) { 32 for (int j = min_col; j < i + min_col; j++) len[j] += i; 33 cnt[i]--; 34 dfs(index + 1); 35 cnt[i]++; 36 for (int j = min_col; j < i + min_col; j++) len[j] -= i; 37 } 38 } 39 } 40 } 41 int main() 42 { 43 int t; 44 cin >> t; 45 while (t--) { 46 cin >> size_cake >> n; 47 int sum = 0, tmp; 48 memset(len, 0, maxn + 5); 49 memset(cnt, 0, maxn + 5); 50 for (int i = 0; i < n; i++) { 51 cin >> tmp; 52 cnt[tmp]++; 53 sum += tmp * tmp; 54 } 55 ok = 0; 56 if (sum == size_cake * size_cake) 57 dfs(0); 58 if (ok) cout << "KHOOOOB!" << endl; 59 else cout << "HUTUTU!" << endl; 60 } 61 }