POJ1020 Anniversary Cake
题目来源:http://poj.org/problem?id=1020
题目大意:有一块边长为s的正方形大蛋糕,有n个客人,每个客人想分一块边长为si的正方形蛋糕。求这块大蛋糕能否恰好满足所有客人的需求而不浪费。
输入:第一行为测试用例数。接下来每行的第一个数位大蛋糕的边长,第二个数位客人的数目n,接下来的n个数为每个客人想要的蛋糕的边长。
输出:若能恰好分完输出“KHOOOOB!”,否则输出“HUTUTU!”
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!
一开始用贪心方法做,即从大块的开始切,总是选最靠近左下角的位置开始切。大多数用例都可以通过,直到遇到这组数据:
10 14 1 1 1 1 1 4 4 3 3 3 3 3 3 3
发现贪心是有问题的。
后来看了牛人的思路,用DFS解决。
切蛋糕时总是自下而上,自左而右。优先切大蛋糕。
解决方案精彩的地方不在于DFS本身,而在于每切一次蛋糕,标记所有蛋糕位置的方法。标记每个格子的状态再查找会TLE。牛人想到的方法是把蛋糕“按列标记”。建立一维数组,d[s],s为大蛋糕边长,d[i]记录每列第一个为空的格子的行号。
1 ////////////////////////////////////////////////////////////////////////// 2 // POJ1020 Anniversary Cake 3 // Memory: 268K Time: 485MS 4 // Language: C++ Result: Accepted 5 ////////////////////////////////////////////////////////////////////////// 6 #include <iostream> 7 using namespace std; 8 9 int s, n; 10 int c[11]; 11 int d[41]; 12 13 int sum; 14 bool ok; 15 16 void reset() { 17 memset(c, 0, sizeof(c)); 18 for (int i = 0; i < 41; ++i) { 19 d[i] = 1; 20 } 21 sum = 0; 22 ok = false; 23 } 24 25 void dfs(int a) { 26 if (a == n) { 27 ok = true; 28 exit; 29 } 30 int i, j; 31 int row, clo; 32 bool f; 33 for (i = 1, clo = 41; i <= s; ++i) { 34 if (d[i] < clo) { 35 clo = d[i]; 36 row = i; 37 } 38 } 39 for (i = 10; i > 0; --i) { 40 if (c[i] > 0 && row + i - 1 <= s && clo + i - 1 <= s) { 41 for (j = row, f = true; j <= row + i - 1; ++j) { 42 if (d[j] > clo) { 43 f = false; 44 break; 45 } 46 } 47 if (f) { 48 for (j = row; j <= row + i - 1; ++j) { 49 d[j] += i; 50 } 51 --c[i]; 52 dfs(a + 1); 53 ++c[i]; 54 for (j = row; j <= row + i - 1; ++j) { 55 d[j] -= i; 56 } 57 } 58 } 59 } 60 } 61 62 int main(void) { 63 int nCase; 64 cin >> nCase; 65 for (int caseNo = 1; caseNo <= nCase; ++caseNo) { 66 reset(); 67 cin >> s >> n; 68 for (int i = 1; i <= n; ++i) { 69 int t ; 70 cin >> t; 71 ++c[t]; 72 sum += t * t; 73 } 74 if (sum != s * s) { 75 cout << "HUTUTU!" << endl; 76 continue; 77 } 78 dfs(0); 79 if (ok) { 80 cout << "KHOOOOB!" <<endl; 81 } 82 else { 83 cout << "HUTUTU!" << endl; 84 } 85 } 86 system("pause"); 87 return 0; 88 }