CodeForces 679B - Bear and Tower of Cubes


题意:有各种棱长a(a>=1)的正方体,体积为a ^ 3,一个物体的体积由各个正方体的体积相加而成

            现求一个体积不超过m的物体,使其使用的正方体数量最多(若一样多则使体积尽量大)

            但每次用正方体垒物体时,必须选不超过目前可使用的剩余体积的最大正方体。

               最后输出使用的正方体数量和物体的体积。


思路:设此时剩余可使用体积为m,目前总共使用体积为sum,则有两种选择:

            1、选不超过此时m的最大正方体(设边长为a),则剩余可使用体积为m - a ^ 3,总共使用体积为sum + a ^ 3。

            2、设不超过此时m的最大正方体边长为a,则将此时的体积设为a ^ 3 - 1,则剩余的可使用体积为a ^ 3 - 1 - (a - 1) ^ 3,总共使用的体积为sum +(a - 1) ^ 3。

            2的原因:以m = 12为例,

            如果执行1,则使用的正方体数量为5(12 - 8 = 4, 4 - 1 = 3, 3 - 1 = 2, 2 - 1 = 1, 1 -  1 = 0),

            如果执行2,则此时的体积变为 8 - 1 = 7, 则使用的正方体数量为7(7个减1)

            即,如果一直贪心使用边长为a的,那么有可能用剩余的体积来选正方体,不如使用 a - 1 为边长的正方体所使用的数量多

            不选 a - 2 以及 a - 3 的正方体:因为立方数1, 8, 27, 64, 125……都是m - (a - 1) ^3 > (a - 2) ^ 3,故选完一个(a - 1)为棱长的正方体后,必有剩余体积可以再选(a - 2)的,所以只需选(a - 1)的即可。



<span style="font-size:12px;">#include<cstdio>
#include<cstring>
#include<cctype>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<list>
typedef long long ll;
typedef unsigned long long llu;
const int MAXN = 100 + 10;
const int MAXT = 100000 + 10;
const int INF = 0x7f7f7f7f;
const double pi = acos(-1.0);
const double EPS = 1e-6;
using namespace std;

ll sta[MAXT], ans1, ans2, n;

void init(){
    for(int i = 0; i < MAXT; ++i)
        sta[i] = (ll)i * (ll)i * (ll)i;
}

void dfs(ll m, ll dot, ll sum){
    if(m == 0){
        if(ans1 < dot)  {ans1 = dot;  ans2 = sum;}
        else if(ans1 == dot && ans2 < sum)  ans2 = sum;
        return;
    }
    int lur = upper_bound(sta, sta + MAXT, m) - sta - 1;
    dfs(m - sta[lur], dot + 1, sum + sta[lur]);
    if(lur >= 1)
        dfs(sta[lur] - (llu)1 - sta[lur - 1], dot + (llu)1, sum + sta[lur - 1]);
}

int main(){
    init();
    ans1 = ans2 = 0;
    scanf("%I64d", &n);
    dfs(n, 0, 0);
    printf("%I64d %I64d\n", ans1, ans2);
    return 0;
}</span>




          



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值