• 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 }
    View Code
  • 相关阅读:
    js常用框架原理
    移动端input解决键盘问题 方案1
    jq大体架构。先记录再慢慢剖析
    把图片存储 canvas原生API转成base64
    清除浮动的6中方法
    window.location.hash属性介绍
    前端性能优化之js,css调用优化
    数组中的对象,判断是否有重复值、
    [Python] Pitfalls: Be Careful with os.chdir
    Changing the Color of Linux ls Command 改变Linux的ls命令显示的颜色
  • 原文地址:https://www.cnblogs.com/dengeven/p/3228146.html
Copyright © 2020-2023  润新知