• 洛谷P1731 生日蛋糕


    P1731 生日蛋糕

    题目背景

    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<=20000),表示待制作的蛋糕的体积为Nπ;第二行为M(M<=15),表示蛋糕的层数为M。

    输出格式:

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

    输入输出样例

    输入样例#1:
    100
    2
    
    输出样例#1:
    68
    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,ans=0x7fffffff,mn[20],mnn[20];
    void dfs(int pos,int pr,int ph,int s,int v){
        if(pos==0){
            if(v==0)ans=min(ans,s);
            return;
        }
        if(v<=0)return;
        if(v-mn[pos]<0)return;
        if(s+mnn[pos]>=ans)return;
        for(int i=pos;i<=pr-1;i++)
            for(int j=pos;j<=min((v-mn[pos-1])/(i*i),ph-1);j++)
                dfs(pos-1,i,j,s+2*i*j,v-i*i*j);
    }
    int main(){
        freopen("Cola.txt","r",stdin);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)mn[i]=mn[i-1]+i*i*i,mnn[i]=mnn[i-1]+2*i*i;
        for(int i=m;i*i<=(n-mn[m-1])/m;i++){
            for(int j=m;j<=(n-mn[m-1])/(i*i);j++){
                dfs(m-1,i,j,i*i+2*i*j,n-i*i*j);
            }
        }
        if(ans==0x7fffffff)puts("0");
        else printf("%d",ans);
        return 0;
    }
    40分 TLE
    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,ans=0x7fffffff,mn[20],mnn[20];
    void dfs(int pos,int pr,int ph,int s,int v){
        if(pos==0){
            if(v==0)ans=min(ans,s);
            return;
        }
        if(v<=0)return;
        if(v-mn[pos]<0)return;
        if(s+mnn[pos]>=ans)return;
        for(int i=pr-1;i>=pos;i--)
            for(int j=min((v-mn[pos-1])/(i*i),ph-1);j>=pos;j--)
                dfs(pos-1,i,j,s+2*i*j,v-i*i*j);
    }
    int main(){
        freopen("Cola.txt","r",stdin);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)mn[i]=mn[i-1]+i*i*i,mnn[i]=mnn[i-1]+2*i*i;
        for(int i=m;i*i<=(n-mn[m-1])/m;i++){
            for(int j=m;j<=(n-mn[m-1])/(i*i);j++){
                dfs(m-1,i,j,i*i+2*i*j,n-i*i*j);
            }
        }
        if(ans==0x7fffffff)puts("0");
        else printf("%d",ans);
        return 0;
    }
    50分 从大到小枚举
    #include<bits/stdc++.h>
    #define oo 1000000000
    using namespace std;
    int ans,a[20],b[20];
    int minn[20];
    int n,m;
    void dfs(int k,int r,int h,int s,int v)//分别存层数 当前层的半径 高度 表面积 剩下的体积 
    {
        if (s+2*v/r>ans) return;//我们知道剩余的体积,能不能根据体积,估算一个剩余的侧面积,如果( 当前的表面积+余下的侧面积的最小值)比最优值还大,那么当前层的搜索就没有意义。
        if (v-minn[m-k]<0) return;//如果剩余的体积按最少的标准,都不能让蛋糕都做不了m层
        if (k==m)//边界情况 
        {
            if (v==0) if (ans>s) ans=s;
            return;
        }
        for (int tr=r-1;tr>=m-k;tr--)
        for (int th=h-1;th>=m-k;th--)//不断缩小半径和高度 进行枚举 
        {
            int ts,tv;
            ts=s+2*tr*th;
            tv=v-tr*tr*th;
            dfs(k+1,tr,th,ts,tv);
        }
    }
    int main()
    {
        cin>>n>>m;
        ans=oo;
        int j=1;
        for (int i=1;i<=m;i++)//预处理一个数组将最小的存起来 等会剪枝 
        {
            minn[i]+=i*i*j;
            j++;
        }
        for (int r=m;r*r<=int(double(n)/m);r++)//因为半径是越来越小的 所以r的大致范围可以确定 
        for (int h=n/(r*r);h>=m;h--)//高度的大致范围也可以确定 
        {
            int s,v;//表面积和剩下的体积 
            s=r*r+2*r*h;//第一层的侧面积+总顶面积(可以通过平移使所有顶面积拼成第一层的顶面积) 
            v=n-r*r*h;
            dfs(1,r,h,s,v);
        } 
        if (ans==oo) ans=0;
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    让windows cmd也用上linux命令
    数据库工具toad与plsql
    Oracle表&DATA复制
    主流WEB开发语言简单对比
    游戏中的碰撞检测
    LRU算法总结及其C算法实现
    MTU
    多款as3游戏框架
    请问2.3e+71,是不是表示23后面有70个0?
    希望OFFICE有一个小阳台,在阳光斜照的下午,开发人员能喝着茶,在蓝色的天空下讨论问题,这样思绪更为清楚
  • 原文地址:https://www.cnblogs.com/thmyl/p/7687200.html
Copyright © 2020-2023  润新知