每日一题 day53 打卡
Analysis
观察一个蛋糕的俯视图,上表面的面积其实就是最下面那一层的底面积,所以在第一次搜索的时候加入这个底面积,之后就只用考虑侧面积就好啦.
就是每次枚举r和h,如何选取上下界呢?
将上一层的高度记作lh,上一层的半径记作lr,则上界很好判断,就是lh−1和lr−1,
底层应该是选取三次根号下20000约为28的范围
现在考虑下界:
自然选取1是会T得很惨的,下界就是最小值嘛,最上面一层的r和h的最小值都是1啊,那还有几层下界就是几啦!
然后来愉快地剪枝:
比较好想的剪枝是这两个:
-
当当前的面积总和已经超过之前的答案时,return
-
当当前体积超过了要求的体积时,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 }
请各位大佬斧正(反正我不认识斧正是什么意思)