905 AlvinZH的奇幻猜想——三次方

思路

中等题。题意简单,题目说得简单,把一个数分成多个立方数的和,问最小立方数个数。

脑子转得快的马上想到贪心,从最近的三次方数往下减,反正有1^3在最后撑着保证减完。不好意思这是错的,因为1,27,64,125...等立方数之间并不是倍数关系,不能构成贪心策略。举个反例:96=64+8+8+8+8=64+27+1+1+1+1+1,答案明显是5,而贪心会算到7。

既然不是贪心,那就是DP了,没毛病。先讲一下常规做法吧,是这样想的:相当于把一个数化成几份,求最小划分的份数,那么把所求数看成背包的总体积,每个立方数的值看作每个物品的体积,价值都看做1,问题就转化为完全背包(因为每个立方数可以取多次)恰好装满求最小的价值,仔细想想。

所以,套一下完全背包的板子吧,但是,这里的一个问题是完全背包装满,这怎么办呢(可能由于本题可以保证装满这个问题不怎么显眼)。举一反三,假设有可能装不满,怎么办?这个问题初始化dp数组时就可以解决。以下方法对于01背包同样适用:

  • 普通01背包or完全背包:初始化为0;
  • 01背包or完全背包装满求价值最小:初始化为一个大数值如 \(INF\) (0x3f3f3f3f);
  • 01背包or完全背包装满求价值最大:初始化为一个小数值如 \(-INF\) (-0x3f3f3f3f);

为什么呢?对于本题,初始化为大数值,如果没装满,最后dp[n]会依然是INF,因为我们每次比较取的都是较小值。第二次练习赛的G题就是01背包装满求最大价值,初始化为最小值即可。(熬夜写了这么多,希望大家看得到QAQ)

这题还有另外的解法,那就是类似打表,先把所有数的最小立方个数通过迭代计算得到,然后 \(O(1)\) 时间取得答案。具体可见队列迭代的参考代码二以及for循环迭代的参考代码三。其实这里面也是有DP的思想,因为每次迭代会用到之前的结果,对于多组数据来讲,同样可以节省时间。简单易懂,可以学习一下。

分析

对于完全背包直接解法,时间复杂度为 \(O(V*∑(V/wi))\) 。

迭代的话复杂度差不了多少,由于多组数据的原因,迭代打表运行总时间显得更短些,不纠结这个。

扩展:完全背包装满问题:HDU 1114。

参考代码一:完全背包装满求最小价值

//
// Created by AlvinZH on 2017/10/24.
// Copyright (c) AlvinZH. All rights reserved.
// #include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
#define MaxSize 1000005 int weight[105];
int ans[MaxSize]; int main()
{
for (int i = 1; i < 105; ++i)
weight[i] = i * i * i; int n;
while(~scanf("%d", &n))
{
for (int i = 0; i <= n; ++i)//初始化为最大值
ans[i] = INF; ans[0] = 0; for (int i = 0; i < 105; ++i) {
for (int j = weight[i]; j <= n; ++j) {
if(ans[j] > ans[j-weight[i]] + 1)
ans[j] = ans[j-weight[i]] + 1;
}
}
if(ans[n] == n) printf("Oh NO!\n");
else printf("%d\n", ans[n]);
}
} /*
* 完全背包恰好装满问题,求最小值。
*/

参考代码二:队列迭代

//
// Created by AlvinZH on 2017/10/24.
// Copyright (c) AlvinZH. All rights reserved.
// #include <cstdio>
#include <cstring>
#include <queue>
#define INF 0x3f3f3f3f
#define MaxSize 1000005
using namespace std; int weight[105];
int ans[MaxSize];
queue<int> Q; void init()
{
memset(ans, INF, sizeof(ans));
for (int i = 1; i < 105; ++i)
weight[i] = i * i * i; for (int i = 1; i <= 100; ++i) {
ans[weight[i]] = 1;
Q.push(weight[i]);
}
while(!Q.empty())
{
int w = Q.front();
Q.pop();
for (int i = 1; i <= 100; ++i) {
int num = weight[i] + w;
if(num > 1000000) break;
if(ans[num] < INF) continue;
ans[num] = ans[w] + 1;
Q.push(num);
}
}
} int main()
{
init();
int n;
while(~scanf("%d", &n))
{
if(ans[n] == n) printf("Oh NO!\n");
else printf("%d\n", ans[n]);
}
}
/*
* 思路:直接宽搜,把最开始的数扔进队列,反复用队列中的数去更新没更新的数就行了,注意数组别越界。
*/

参考代码三:for循环迭代

/*
Author: 曾宥崴(13422)
Result: AC Submission_id: 391756
Created at: Fri Nov 10 2017 18:26:40 GMT+0800 (CST)
Problem: 905 Time: 353 Memory: 6612
*/ #include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std; int f[1000001],n; int main()
{
for (int i = 1; i <= 1000000; i++) f[i] = 1000000000; f[0] = 0;
for (int i = 0; i <= 1000000; i++)
for (int k = 1; i + k * k * k <= 1000000; k++)
f[i+k*k*k] = min(f[i+k*k*k],f[i] + 1); while (scanf("%d",&n) != EOF)
if (f[n] == n) printf("Oh NO!\n");
else printf("%d\n",f[n]); return 0;
}

2016级算法第三次上机-C.AlvinZH的奇幻猜想——三次方的更多相关文章

  1. 2016级算法第四次上机-F.AlvinZH的最“长”公共子序列

    940 AlvinZH的最"长"公共子序列 思路 DP,难题. \(dp[i][j]\) :记录A的前i个字符与B的前j个字符变成相同需要的最小操作数. 初始化:dp[i][0] ...

  2. 2016级算法第六次上机-F.AlvinZH的学霸养成记VI

    1082 AlvinZH的学霸养成记VI 思路 难题,凸包. 分析问题,平面上给出两类点,问能否用一条直线将二者分离. 首先应该联想到这是一个凸包问题,分别计算两类点的凸包,如果存在符合题意的直线,那 ...

  3. 2016级算法第六次上机-D.AlvinZH的学霸养成记V

    1081 AlvinZH的学霸养成记V 思路 中等题,计算几何. 这是一个排序问题,按极角排序.可以转化为叉积的应用,对于点A和B,通过叉积可以判断角度大小,共线时再判断距离. 叉积的应用.OA × ...

  4. 2016级算法第五次上机-E.AlvinZH的学霸养成记IV

    1039 AlvinZH的学霸养成记IV 思路 难题,最大二分图匹配. 难点在于如何转化问题,n对n,一个只能攻击一个,判断是否存在一种攻击方案我方不死团灭对方.可以想到把所有随从看作点,对于可攻击的 ...

  5. 2016级算法第四次上机-D.AlvinZH的1021实验plus

    978 AlvinZH的1021实验plus 思路 贪心,中等题. 使用miss变量表示未覆盖的最小数字,初始值为1. 初始覆盖区间为[1,miss),目标是覆盖[1,m],即miss需要大于m. 需 ...

  6. 2016级算法第六次上机-C.AlvinZH的学霸养成记II

    1032 AlvinZH的学霸养成记II 思路 中等题,贪心. 所有课程按照DDL的大小来排序. 维护一个当前时间curTime,初始为0. 遍历课程,curTime加上此课程持续时间d,如果这时cu ...

  7. 2016级算法第五次上机-D.AlvinZH的学霸养成记III

    850 AlvinZH的学霸养成记III 思路 难题.概率DP. 第一种思考方式:直接DP dp[i]:从已经有i个学霸到所有人变成学霸的期望. 那么答案为dp[1],需要从后往前逆推.对于某一天,有 ...

  8. 2016级算法第四次上机-C.AlvinZH的1021实验

    975 AlvinZH的1021实验 思路 贪心,简单题. 题目已经说明有且只有一种方法表示所求数,简单列举几项可以发现只由前i个砝码会可以表示[1,∑Wi]的所有数的.先找到最大需要的砝码Wi,问题 ...

  9. 2016级算法第六次上机-E.Bamboo之吃我一拳

    Bamboo之吃我一拳 分析 当两个点的距离<=d时,才可以出拳,想要使得满足出拳条件的点对最少但不为0 寻找最近点对距离,得到的最近距离能够使得可以出拳的组数最少,因为除了最近点对外其他组合均 ...

随机推荐

  1. 269. Alien Dictionary火星语字典(拓扑排序)

    [抄题]: There is a new alien language which uses the latin alphabet. However, the order among letters ...

  2. redis缓存分页思路

    传统分页一般分页做缓存都是直接查找出来,按页放到缓存里,但是这种缓存方式有很多缺点.如缓存不能及时更新,一旦数据有变化,所有的之前的分页缓存都失效了.比如像微博这样的场景,微博下面现在有一个顶次数的排 ...

  3. appium desktop v1.2.7在android7.0上运行报错“Error: Error executing adbExec”

    1.参考下面链接,https://stackoverflow.com/questions/42283921/unable-to-run-appium-tests-on-android-7-0:得知需要 ...

  4. [c++] polymorphism without virtual function

    polymorphism without virtual function

  5. UID, EUID, SUID, FSUID

    摘自:https://blog.csdn.net/wh8_2011/article/details/50825340 UID, EUID, SUID, FSUID 2016年03月08日 10:40: ...

  6. echo $[1 + 2] shell中 $[] 在bash中同$(()),用于算术计算

    shell脚本编写:echo $[ 11#8+1] 输出结果是几,为什么,怎么算来的?  摘自:https://zhidao.baidu.com/question/334766451.html   结 ...

  7. JDBC 连接 MySQL 时碰到的小坑

    最近从MS SQL Server换到了MySQL,已经是8.11版本了,安装的时候似乎还用了新的身份认证方式之类的,连接过程中也是磕磕绊绊,碰到很多奇奇怪怪的问题,在此记录下来. 驱动加载: 以前使用 ...

  8. 使用word 2013 发布csdn博客

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  9. Alpha冲刺 - (9/10)

    Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 进一步优化代码,结合自己负责的部分修 ...

  10. 【微服务架构】SpringCloud之Hystrix断路器(六)

    一:什么是Hystrix 在分布式环境中,许多服务依赖项中的一些将不可避免地失败.Hystrix是一个库,通过添加延迟容差和容错逻辑来帮助您控制这些分布式服务之间的交互.Hystrix通过隔离服务之间 ...