NOI1999] birthday cake

table of Contents

Topic Link

P1731 [NOI1999] birthday cake

Thinking

Search + pruning

With $ mins [i] $ $ I $ denotes the surface area of ​​the smallest layer $ minv [i] $ $ I $ denotes the minimum volume level, for the first set bottom $ $ n-layer, each layer enumerated high and radius .

But this complexity is the complexity of God

So to add optimization (pruning)

We first look at the title of a few details:

When $ i <When M $, requires $ R_i> R_ {i + 1} and H_i> H_ {i + 1} $

Sentence tells us a good thing, when we enumeration radius and height can be determined upper and lower bounds , and this is a pruning

Second detail:

Look at this chart you will find that the bottom layer of the bottom area is not that the surface area above and (that is, where black figure below)

So it seems we just enumerate the lowest is recorded about $ i \ times i $ would not have considered blacked-out portions, and simplifying procedures

Look at other pruning:

1. If the current minimum surface area has been searched is greater than the surface area of the smallest known exit
2. If the currently searched volume has exceeded the limit subject, exit
3. If the current introduced by the surface area to volume have not preferable exit

to sum up:

1. enumeration radius and height can be determined bounds
2. If the current minimum surface area has been searched it is greater than the surface area of the smallest known exit
3. If the currently searched volume limit has been exceeded title exit
4. If the the current surface area to volume launch has not gifted exit

Code

#include<bits/stdc++.h>
using namespace std;
//体积公式:v=piRH
//侧面积:2piRH
//底面积:piR^2
const int MAXN=0x3f3f3f;
const int N=20007;
int ans=MAXN;
int mins[N],minv[N],n,m;
void dfs(int now,int r,int h,int s,int v) {
    //  当前层数 半径  高度 面积  体积
    int MAXN_high=h;
    if(now==0) {
        if(v==n) {
            ans=min(ans,s);
        }
        return ;
    }
    if(s+mins[now-1]>=ans) return ;//如果面积已经大于了目前的最优值ans就可以退出了
    if(v+minv[now-1]>n) return;//如果当前搜到的体积已经大于了题目给定的体积就可以退出了
    if(2*(n-v)/r+s>=ans)  return; //由体积推出的表面积已经大于最大值了就可以退出了
    for(int i=r-1; i>=now; --i) {//枚举半径
        if(now==m) s=i*i;//此处是处理最下面的那个面其实也就是上面的那个,可以看一下解释
        MAXN_high=min(h-1 ,(n-minv[now-1]-v)/i/i);//求出最大的高度来
        for(int j=MAXN_high; j>=now; --j) {
            dfs(now-1,i,j,s+2*i*j,v+i*i*j);
        }
    }
}
int main() {
    cin>>n>>m;
    /*初始化每层成最小的表面积和体积*/
    for(int i=1; i<=m; ++i) {
        mins[i]=mins[i-1]+2*i*i;//计算面积
        minv[i]=minv[i]+i*i*i;//计算体积
    }
    dfs(m,n,n,0,0);//开始dfs喽
    if(ans==MAXN) cout<<0<<'\n';
    else cout<<ans<<'\n';
    return 0;
}

Guess you like

Origin www.cnblogs.com/pyyyyyy/p/11123220.html