题意:有各种棱长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>