analysis
搜索
基本框架
显然搜索每一层的h和r即可
关于hi和ri的范围,有如下推导:
根据圆柱体积公式:
V n o w = π r 2 h V_{now}=\pi r^2h Vnow=πr2h
极端情况下,高为1
于是
V
n
o
w
=
π
r
2
V_{now}=\pi r^2
Vnow=πr2
按照题意约掉
π
\pi
π得到
r
=
V
n
o
w
=
N
−
v
n
o
w
r=\sqrt{V_{now}}=\sqrt{N-v_{now}}
r=Vnow=N−vnow
而题中还有一个条件,就是 R i < R i + 1 → R i < = R i + 1 − 1 R_i<R_{i+1}\rightarrow R_i<=R_{i+1}-1 Ri<Ri+1→Ri<=Ri+1−1
于是 R ∈ [ l a y e r , m i n ( N − v n o w , r l a y e r + 1 − 1 ) ] R\in[layer,min(\sqrt{N-v_{now}},r_{layer+1}-1)] R∈[layer,min(N−vnow,rlayer+1−1)]
当枚举好R了以后,
V n o w = π R 2 H V_{now}=\pi R^2H Vnow=πR2H
H = V n o w R 2 = ⌊ ( N − v ) / R 2 ⌋ H=\frac{V_{now}}{R^2}=⌊(N-v)/R^2⌋ H=R2Vnow=⌊(N−v)/R2⌋
题中同样还有一个条件,就是 H i < H i + 1 → H i < = H i + 1 − 1 H_i<H_{i+1}\rightarrow H_i<=H_{i+1}-1 Hi<Hi+1→Hi<=Hi+1−1
于是 H ∈ [ l a y e r , m i n ( ⌊ ( N − v ) / R 2 ⌋ , H l a y e r + 1 − 1 ) ] H\in[layer,min(⌊(N-v)/R^2⌋,H_{layer+1}-1)] H∈[layer,min(⌊(N−v)/R2⌋,Hlayer+1−1)]
剪枝
- 优化搜索顺序
- 定义对于每一层的ri和hi倒序枚举
- 排除等效冗余
- EOF…
- 可行性剪枝
- 鉴于前面用了倒序枚举,一开始枚举的状态可能会过大,因此我们要预算一下最小的体积,如果当前枚举的体积加上最小的后续体积比要求的体积大,那么就不可能在拓展了
- 最优化剪枝
- 借鉴可行性剪枝第一条的思路,预算一下最小的表面积,如果当前表面积加上后续最小表面积大于当前搜出来的最优解的时候就没有必要拓展了
- 放缩法估计花费剪枝:
考虑寻找第dep层的h或r和1到dep层的表面积的等或不等关系,从而用第dep层的数据来预判是否最优
第1到dep-1层的表面积可表示为(约掉 π \pi π后,不计上表面积):
S = 2 ∗ ( h [ 1 ] ∗ r [ 1 ] + h [ 2 ] ∗ r [ 2 ] . . . . . . + h [ d e p − 1 ] ∗ r [ d e p − 1 ] ) = 2 ∗ ∑ i − 1 d e p − 1 h [ i ] ∗ r [ i ] S=2*(h[1]*r[1]+h[2]*r[2]......+h[dep-1]*r[dep-1])=2*\sum_{i-1}^{dep-1}h[i]*r[i] S=2∗(h[1]∗r[1]+h[2]∗r[2]......+h[dep−1]∗r[dep−1])=2∗i−1∑dep−1h[i]∗r[i]
对S进行变形:
S = 2 ∗ ( h [ 1 ] ∗ r [ 1 ] + h [ 2 ] ∗ r [ 2 ] . . . . . . + h [ d e p − 1 ] ∗ r [ d e p − 1 ] ) S=2*(h[1]*r[1]+h[2]*r[2]......+h[dep-1]*r[dep-1]) S=2∗(h[1]∗r[1]+h[2]∗r[2]......+h[dep−1]∗r[dep−1])
= 2 r [ d e p ] ( h [ 1 ] ∗ r [ 1 ] ∗ r [ d e p ] + h [ 2 ] ∗ r [ 2 ] ∗ r [ d e p ] . . . . . . + h [ d e p − 1 ] ∗ r [ d e p − 1 ] ∗ r [ d e p ] ) =\frac{2}{r[dep]}(h[1]*r[1]*r[dep]+h[2]*r[2]*r[dep]......+h[dep-1]*r[dep-1]*r[dep]) =r[dep]2(h[1]∗r[1]∗r[dep]+h[2]∗r[2]∗r[dep]......+h[dep−1]∗r[dep−1]∗r[dep])
由于 r [ d e p ] > = r [ i ] , i ∈ [ 1 , d e p ] r[dep]>=r[i],i\in[1,dep] r[dep]>=r[i],i∈[1,dep]
于是 S > = 2 r [ d e p ] ( h [ 1 ] ∗ r [ 1 ] 2 + h [ 2 ] ∗ r [ 2 ] 2 . . . . . . + h [ d e p − 1 ] ∗ r [ d e p − 1 ] 2 ) S>=\frac{2}{r[dep]}(h[1]*r[1]^2+h[2]*r[2]^2......+h[dep-1]*r[dep-1]^2) S>=r[dep]2(h[1]∗r[1]2+h[2]∗r[2]2......+h[dep−1]∗r[dep−1]2)
由于第1到dep-1层的体积可表示为(约掉 π \pi π后):
n − v = h [ 1 ] ∗ r [ 1 ] 2 + h [ 2 ] ∗ r [ 2 ] 2 + . . . . . . + h [ d e p − 1 ] ∗ r [ d e p − 1 ] 2 = ∑ i = 1 d e p − 1 h [ i ] ∗ r [ i ] 2 n-v=h[1]*r[1]^2+h[2]*r[2]^2+......+h[dep-1]*r[dep-1]^2=\sum_{i=1}^{dep-1}h[i]*r[i]^2 n−v=h[1]∗r[1]2+h[2]∗r[2]2+......+h[dep−1]∗r[dep−1]2=i=1∑dep−1h[i]∗r[i]2
于是 S > = 2 ( n − v ) r [ d e p ] S>=\frac{2(n-v)}{r[dep]} S>=r[dep]2(n−v)
这个式子意思就是:从1到dep-1层的表面积一定会大于等于 2 ( n − v ) r [ d e p ] \frac{2(n-v)}{r[dep]} r[dep]2(n−v)
于是当我们搜到第dep层的时候,可以用这个式子来估计未来的最小预算会不会超过当前的最优值,也就是说当 2 ( n − v ) r [ d e p ] + s n o w > b e s t c o s t \frac{2(n-v)}{r[dep]}+s_{now}>bestcost r[dep]2(n−v)+snow>bestcost的时候剪枝
- 记忆化
- 本题没有记忆化的必要
code
#include <bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define ll long long
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
#define pi 1
#define Val(h,r) (pi*r*r*h)
#define Sur(h,r) (2*pi*r*h)
#define Area(r) (pi*r*r)
#define re register
int n,m;
const int maxn=20000+10;
const int maxm=20;
int minn=INT_MAX;
int minnv[maxm];
int minns[maxm];
int ri[maxm];
int hi[maxm];
void dfs(re int layer,re int nv,re int cost){
if(cost+Area(ri[m])>minn||2*(n-nv/pi)/ri[layer+1]+cost>minn)
return;
if(nv+minnv[layer-1]>n*pi||cost+minns[layer-1]>minn)
return;
if(layer<=0){
if(nv==pi*n)
minn=min(minn,cost+Area(ri[m]));
return;
}
for(register int r=min(ri[layer+1]-1,(int)sqrt(n-nv/pi));r>=layer;--r){
for(register int h=min(hi[layer+1]-1,(n-nv/pi)/(r*r));h>=layer;--h){
ri[layer]=r;
hi[layer]=h;
dfs(layer-1,nv+Val(h,r),cost+Sur(h,r));
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif
read(n);
read(m);
loop(i,1,m)
minnv[i]=minnv[i-1]+Val(i,i),
minns[i]=minns[i-1]+Sur(i,i)+Area(i);
hi[m+1]=n;
ri[m+1]=n;
dfs(m,0,0);
printf("%d\n",minn/pi);
return 0;
}