Luo Gu P1731 [NOI1999] birthday cake

topic

Search + prune, and mainly on the details of the search order, all data can be found are first integer, initializes each of R and H is an integer of cake, and then to search for the lower layer, the lower layer and the layers from the pretreatment top minimum volume and area for pruning.

Each layer can enumerate the current maximum radius to the minimum radius, and classified to discuss adding prune.

#include <bits/stdc++.h>
using namespace std;    
int n, m, S[1001], V[1001];//最小面积和体积
struct cak {
    int R, H, CS, S, V;
}data[1001];
int minn = 2147483647;
void dfs(int now, int nS, int nV, int R, int H)//now层数,nS当前蛋糕面积,nV当前蛋糕体积,R最大半径,H最大高度
{ 
    if (now == 0)
    {
        if (nV == n)
        minn = min(minn, nS);
        return;
    }
    if (nS + S[now - 1] > minn) return;//如果当前的蛋糕面积加上最小的面积大于minn 
    if (nV + V[now - 1] > n) return;//如果当前的蛋糕体积加上最小的体积比n大。
    if (2 * (n - nV) / R + nS >= minn)  return;//如果当前体积所换算成的面积大于minn 
    for (int i = R; i >= data[now].R; i--)//i一定比data[now].R 
    {
        if ( now == m )
            nS = i * i;
        int tot = min( H, (n - (nV + V[now - 1])) / (i * i) );//tot是接下来要取到的h的最小值, 
        for (int j = tot; j >= data[now].H; j--)
            dfs(now - 1, nS + 2 * i * j, nV + i * i * j, i - 1, j - 1);
    }
}
inline void init()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++)
        data[i].R = i, data[i].H = i, data[i].CS = data[i].H * data[i].R * 2, data[i].S = data[i].R * data[i].R, data[i].V = data[i].S * data[i].H;
    for (int i = 1; i <= m; i++)
        S[i] = S[i - 1] + data[i].CS, V[i] = V[i - 1] + data[i].V;
}
int main()
{
    init();
    dfs(m, 0, 0, 25, 25);
    if (minn == 2147483647) printf("0");
    else printf("%d", minn);
    return 0;
}

Guess you like

Origin www.cnblogs.com/liuwenyao/p/11104008.html