upc 7833 生日蛋糕

生日蛋糕

时间限制: 1 Sec  内存限制: 128 MB
提交: 2  解决: 2
[提交] [状态] [讨论版] [命题人:admin]

题目描述

7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i<M时,要求Ri>Ri+1且Hi>Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q= Sπ,请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。(除Q外,以上所有数据皆为正整数)

输入

有两行,第一行为N(N<=10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M<=20),表示蛋糕的层数为M。

输出

仅一行,是一个正整数S(若无解则S=0)。

样例输入

100
2

样例输出

68

提示

体积V=πR2H
侧面积A’=2πRH
底面积A=πR2

题意

找每一层合适的r,h,使得最后的面积s最小。输出s。

分析

真的是毫无头绪,要不是在搜索专题真不觉得是个搜索题。

想明白了还是挺简单的。直接的dfs不可行,需要一些剪枝。

1、设下一层的最大体积为v,剩余体积为left_v,还剩余x层未搜索,如果x*v<left_v。一句话就是:剩下的体积用不完了。

2、如果当前的面积已经比之前记录的最小面积大,那就没有必要继续搜了。

///  author:Kissheart  ///
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<deque>
#include<ctype.h>
#include<map>
#include<set>
#include<stack>
#include<string>
#define INF 0x3f3f3f3f
#define FAST_IO ios::sync_with_stdio(false)
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAX=1e5+10;
const int mod=1e9+7;
typedef long long ll;
using namespace std;
#define gcd(a,b) __gcd(a,b)
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
inline ll inv1(ll b){return qpow(b,mod-2);}
inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll r=exgcd(b,a%b,y,x);y-=(a/b)*x;return r;}
inline ll read(){ll x=0,f=1;char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;for(;isdigit(c);c=getchar()) x=x*10+c-'0';return x*f;}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
int n,m;
int ans;
void dfs(int x,int left_v,int pre_r,int pre_h,int sum)
{
    if(!x && !left_v)
    {
        if(ans)
            ans=min(sum,ans);
        else
            ans=sum;
        return ;
    }

    if(x*(pre_r-1)*(pre_r-1)*(pre_h-1)<left_v && x!=m)
        return ;
    if(x<=0 || left_v<=0 || (sum>=ans && ans))
        return ;
    for(int i=pre_r-1;i>=x;i--)
    {
        for(int j=pre_h-1;j>=x;j--)
        {
            int s=2*i*j;
            int v=i*i*j;
            if(x==m) s+=i*i;
            if(2*left_v/i+sum>=ans && ans)
                continue;
            dfs(x-1,left_v-v,i,j,sum+s);
        }
    }

}
int main()
{
    scanf("%d%d",&n,&m);
    dfs(m,n,1000,100,0);

    printf("%d
",ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Kissheart/p/9769216.html