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


    搜索剪枝,

    1.枚舉上下界:

    先$Rsubset$$(dep,min(lfloorsqrt{n-v} floor,lastr-1))$

    后$Hsubset$$(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}$

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

    因為

    $2sum_{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$首使用

  • 相关阅读:
    ES6 解构
    flutter
    selenium
    selenium
    python
    selenium
    selenium
    selenium
    selenium
    selenium- SMTP发送邮件
  • 原文地址:https://www.cnblogs.com/superminivan/p/10957457.html
Copyright © 2020-2023  润新知