题目

源地址:

http://poj.org/problem?id=1190

理解

这道题是学长推荐的DFS练习题,一开始没有想明白,为什么这道题是DFS。多次推导之后发现,这道题确实需要用到深度搜索。每次都先确定第一层蛋糕的体积数,然后减去得到剩余的蛋糕体积,如此循坏,最后要保证最后的体积和等于给定的N。因为半径是递增的,所以可以去掉很大一部分无效的搜索。

代码


#include <cstdio>
#include <cmath>
using namespace std;

int N, S, M;
int end, min;

int dfs(int v, int m, int lastr, int lasth)
{
    if (m == 0)
    {
        if (v > 0 || v < 0)
            return 0;
        else
        {
            end = 1;
            if (min < S)
                S = min;
            return 0;
        }
    }
    int i, t = 0, j, k, temp;
    for (i = 1; i <= m; i++)
        t += i * i * i;
    if (v < t)
        return 0;
    t -= m * m * m;
    int maxr, maxh;
    maxr = (int)sqrt((v - t) * 1.0 / m) < lastr ? (int)sqrt((v - t) * 1.0 / m) : lastr;
    for (i = maxr; i >= m; i--)
    {
        maxh = (v - t) / (i * i) < lasth ? (v - t) / (i * i) : lasth;
        for (j = maxh; j >= m; j--)
        {
            temp = 0;
            for (k = 0; k <= m - 1; k++)
                temp += (i - k) * (i - k) * (j - k);
            if (v > temp)
                break;
            int tempv = v - i * i * j;
            if (m == M)
            {
                if (i * i < S)
                    min = i * i;
                else
                {
                    tempv = v;
                    continue;
                }
            }
            min += 2 * i * j;
            if (min > S)
            {
                tempv = v;
                min -= 2 * i * j;
                continue;
            }
            dfs(tempv, m - 1, i - 1, j - 1);
            min -= 2 * i * j;
        }
    }
    return 0;
}


int main(int argc, char const *argv[])
{
    while (scanf("%d%d", &N, &M) == 2)
    {
        int t = 0;
        end = 0;
        S = 100000;
        dfs(N, M, 1000, 1000);
        if (!end)
            S = 0;
        printf("%d\n", S);
    }
    return 0;
}

更新日志

  • 2014年07月12日 已AC。