POJ----1190

剪枝+dfs

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int N, M;
int best;
int leftMinS[22], leftMinV[22];

void dfs(int now, int sumS, int sumV, int r, int h)
{
    if(now==0)
    {
        if(sumV==N && best>sumS)
            best = sumS;
        return;
    }

    if(sumS+leftMinS[now]>best || sumV+leftMinV[now]>N)
        return;

    /**
     *  2*r*h=S
     *  r*r*h=V
     *  => V*2/r = S
     *  S + sumS >= best => return;
     */
    if((2*(N-sumV)/r + sumS) >=best)
        return;

    for(int i=r-1; i>=now; i--)
    {
        if(now==M)
            sumS = i*i;
        int maxH = min((N-leftMinV[now-1]-sumV)/(i*i), h-1);
        for(int j=maxH; j>=now; j--)
        {
            dfs(now-1, sumS+i*j*2, sumV+i*i*j, i, j);
        }
    }
}


int main()
{
    leftMinS[0] = 0;
    leftMinV[0] = 0;
    for(int i=1; i<22; i++)
    {
        leftMinS[i] = leftMinS[i-1] + i*i*2;
        leftMinV[i] = leftMinV[i-1] + i*i*i;
    }
    scanf("%d", &N);
    getchar();
    scanf("%d", &M);
    getchar();
    best = 9999999;
    dfs(M, 0, 0, 100, 10000);
    if(best==9999999) best = 0;
    printf("%d\n", best);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值