洛谷 P1731 [NOI1999]生日蛋糕 题解

每日一题 day53 打卡

Analysis

观察一个蛋糕的俯视图,上表面的面积其实就是最下面那一层的底面积,所以在第一次搜索的时候加入这个底面积,之后就只用考虑侧面积就好啦.

就是每次枚举r和h,如何选取上下界呢?

将上一层的高度记作lh,上一层的半径记作lr,则上界很好判断,就是lh−1和lr1

底层应该是选取三次根号下20000约为28的范围

现在考虑下界:

自然选取1是会T得很惨的,下界就是最小值嘛,最上面一层的r和h的最小值都是1啊,那还有几层下界就是几啦!

然后来愉快地剪枝:

比较好想的剪枝是这两个:

  1. 当当前的面积总和已经超过之前的答案时,return

  2. 当当前体积超过了要求的体积时,return

还有一些剪枝,思维难度也不算高:

  • 当现在的已有体积加上之后的最大(并不是真正的最大,会比最大还要大一些)体还要小于要求的体积时,return

  • 当当前的已有面积加上之后的最小(自然也是比真正的最小还要小一些)面积比已有答案还要大时,return

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define int long long
 6 #define INF 2147483647
 7 #define rep(i,s,e) for(register int i=s;i<=e;++i)
 8 #define dwn(i,s,e) for(register int i=s;i>=e;--i)
 9 using namespace std;
10 inline int read()
11 {
12     int x=0,f=1;
13     char c=getchar();
14     while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
15     while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
16     return f*x;
17 }
18 inline void write(int x)
19 {
20     if(x<0) {putchar('-'); x=-x;}
21     if(x>9) write(x/10);
22     putchar(x%10+'0');
23 }
24 int n,m,ans=INF;
25 void dfs(int layer,int volume,int area,int radius,int height)
26 {
27     if(area>=ans) return;
28     if(layer==m+1&&volume==n)
29     {
30         ans=min(ans,area);
31         return;
32     }
33     if(volume>=n) return;
34     int now_layer=m-layer+1;
35     if(volume+now_layer*radius*radius*height<n) return;
36     if(area+now_layer*2>ans) return;
37     if(layer==1)
38     {
39         rep(r,m,radius)
40             rep(h,m,height)
41                 dfs(layer+1,volume+r*r*h,area+2*r*h+r*r,r,h);
42     }
43     else 
44     {
45         rep(r,now_layer,radius-1)
46             rep(h,now_layer,height-1)
47                 dfs(layer+1,volume+r*r*h,area+2*r*h,r,h);
48     }
49 }
50 signed main()
51 {
52     n=read();m=read();
53     dfs(1,0,0,28,28);
54     if(ans==INF) write(0);
55     else write(ans);
56     return 0;
57 }

请各位大佬斧正(反正我不认识斧正是什么意思)

posted @ 2019-12-02 17:57  handsome_zyc  阅读(239)  评论(0编辑  收藏  举报