POJ1190[DFS经典]

分蛋糕

题目链接

题意:中文提不说了...
题目类型:DFS

题解:如果一开始我单独看到这道题,肯定不会朝搜索方向想。。。这里要积累一下思路。因为M,N的数据范围给定,且数据范围满足递减的要求,因此解空间有限,应该有搜索的想法,看看数据好像可以搜,考验剪枝水平;

爆搜方法,就是每次枚举100以内的半径,1000以内的高,搜索m层(m<=20),如果体积为刚好就存下结果,每一次取最小值;

剪枝部分,如果当前的圆柱半径与高度能够成的最大体积小于剩余体积,就结束;如果当前的面积大于之前搜到的最小面积,就结束;最后一个剪枝,不容易想到,如果到第k层时剩下第k到第M层的面积 2*Ri*Hi>2*Ri*Ri*Hi/Rk=2*Vi, 全部加起来就是 2*leftV, 所以 A+2*leftV>min 可以剪枝;

Code:

#include <iostream>
#include <cstdio>
#include<cstring>
#include<algorithm>
#include <string>
#include <queue>
#include <map>
#define ll long long
#define INF 0x3f3f3f3f

using namespace std;

int N,M,ans=0;

void dfs(int leftv ,int m , int A , int lastR , int lastH)
{
    ///剪枝
    if(A>ans&&ans)return ;
    if(leftv<0)return ;
    if( m * (lastR - 1) * (lastR - 1) * (lastH - 1) < leftv && m != M)return;///当前的极限体积小于剩下的体积
    ///
    if(!m)
    {
        if(!leftv&&(A<ans||!ans))
        {
            ans=A;
        }
        return;
    }
    for(int r = lastR - 1 ; r >= m ; r--)///还剩m层,因此最小半径为m
    {
        for(int h = lastH - 1 ; h >= m ; h--)
        {
            ///剪枝
            if(A+2*leftv/r > ans && ans)///从100ms+优化到32ms
                return ;

            int curv=leftv-r*r*h;
            int curA=A+2*r*h;
            if(m==M)curA+=r*r;///如果是第一层,就加上底面积
            dfs(curv , m - 1 , curA , r , h);
        }
    }

}

int main()
{
    scanf("%d%d",&N,&M);
    dfs(N,M,0,100,1000);
    cout << ans << endl;
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值