[題解](搜索)生日蛋糕(NOI1999)

搜索剪枝,

1.枚舉上下界:

先$R\subset$$(dep,min(\lfloor\sqrt{n-v}\rfloor,lastr-1))$

后$H\subset$$(dep,min((n-v)/R^{2},lasth-1))$

由$\pi R^{2}H=\pi(n-v)$可以推出來,R那裡沒有除H是因為H最小為1

2.優化搜索順序:倒序以減小枚舉規模,應該會更快

3.不太複雜的預估(可行性剪枝

預處理出$1$~$dep-1$層的最小體積前綴和,最小側面積前綴和,每次加一下和$n、ans$比較

4.比較複雜的預估(最優性剪枝

單獨判斷s和v還不太夠,他們之間也有一些約束關係,

$1$~$dep-1$層的體積可表示為$n-v=\sum_{k=1}^{dep-1} h[k]*r[k]^{2}$

表面積可表示為$2\sum_{k=1}^{dep-1} h[k]*r[k]$

因為

$2\sum_{k=1}^{dep-1} h[k]*r[k]=\frac{2}{r[dep]} * \sum_{k=1}^{dep-1} h[k]*r[k]*r[dep] \geqslant \frac{2}{r[dep]} * \sum_{k=1}^{dep-1} * h[k] * r[k]^{2} \geqslant \frac{2(n-v)}{r[dep]}$

所以當$\frac{2(n-v)}{r[dep]}+s$大於答案時剪枝

 

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=20009;
int n,m,ans=999999999;
int smv[maxn],sms[maxn];//最小體積和,最小側面積和 
void dfs(int dep,int s,int v,int lstr,int lsth){
    if(dep==0){
        if(v==n)ans=min(ans,s);return;
    }
    if(v+smv[dep]>n)return;
    if(s+sms[dep]>ans)return;
    if(s+2*(n-v)/lstr>ans)return;
    for(int r=min((int)sqrt(n-v),lstr-1);r>=dep;r--){
        if(dep==m)s=r*r;
        for(int h=min((n-v)/(r*r),lsth-1);h>=dep;h--){
            dfs(dep-1,s+2*r*h,v+r*r*h,r,h);
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        sms[i]=sms[i-1]+2*i*i;
        smv[i]=smv[i-1]+i*i*i;
    }
    dfs(m,0,0,sqrt(n),n);
    if(ans==999999999)printf("0");
    else printf("%d",ans);
}

($LaTeX$首使用

posted @ 2019-05-31 20:53  羊肉汤泡煎饼  阅读(178)  评论(0编辑  收藏  举报