拿糖果问题

问题描述
  妈妈给小B买了N块糖!但是她不允许小B直接吃掉。
  假设当前有M块糖,小B每次可以拿P块糖,其中P是M的一个不大于根号下M的质因数。这时,妈妈就会在小B拿了P块糖以后再从糖堆里拿走P块糖。然后小B就可以接着拿糖。
  现在小B希望知道最多可以拿多少糖。
输入格式
  一个整数N
输出格式
  最多可以拿多少糖
样例输入
15
样例输出
6
数据规模和约定
  N <= 100000

解题思路:
这道题关键在于数字P,首先理解数字P,它有三个条件,其一是质数,其二是M的一个因数,其三要小于根号下M。
接下来看问题,问的是 希望知道最多可以拿多少糖,而拿糖呢 是 有N颗糖拿最多的糖 看到这个熟悉的架构了吗,这表明,从N中拿最多的糖建立在从N-1到1中拿最多的糖的解上,而我们知道,动态规划问题的一个要点在于,整体的最优解,一定建立或包含在子最优解上的,也就说从M中挑选P的最优解,一定建立在从M'中挑选P'的最优解上。通俗的讲,假设有N = 15,我现在已经知道了N = 1 ,2 ,3 。。。14的答案,首先当N = 15时,它的质因数为2或者3.也就是说,我如果拿2颗,那么还剩15 - 2 * 2 = 11颗,而我已经知道了11颗糖的时候我能拿的最多糖果的答案,那么N = 15时,我能拿到的糖果就是当糖果还有11颗是我能拿的数量加上我已经拿的2颗。同理,还要考虑质因数为3的情况,两种情况中那个情况最优,则答案就是那个。
所以我们可以得出递推式:
dp[i] = dp[i - 2 * prime] + prime
其中,i代表当前的糖果数量,dp[i]的值为当糖果数量为I时我能拿的最多的糖果。
当然,我们这个递推式还不完整,还漏了一点。就是会有多个质因数可以供选择,我们必须对于每个质因数都计算一次,然后选其中最大的情况,所以,完善后的递推式为
dp[i] = max( dp[i] , dp[i - 2 * prime] + prime )
当所有准备工作完成后,我们可以开始了

c++代码:

#include <iostream>
#include <vector>
#include <cmath> using std::cout;
using std::cin;
using std::vector;
using std::max; int main()
{
vector<int> prime;
//存放小于等于根号下 number 的所有质数
int number; //等待输入的总糖果数量
bool flag; //状态。判断一个数字是不是质数 cin>>number;
vector<int> dp(number + ,); //dp向量。记录当糖果数量为i时能拿的糖果 //求质数,并将所有质数保存到prime中
int sqt1 = sqrt(number);
for(int i = ; i <= sqt1; ++i)
{
int sqt2 = sqrt(i);
flag = true;
for(int j = ; j <= sqt2; ++j)
{
if(i % j == )
flag = false;
}
if(flag == true)
prime.push_back(i); } //处理dp向量
for(int i = ; i != number + ; ++i) //i代表dp的下标,代表糖果的数量
{
int sqt2 = sqrt(i);
int _size = prime.size();
for(int j = ; j != _size; ++j) //遍历整个质数的数组
{
if(prime[j] <= sqt2 && i % prime[j] == ) //如果这个质数小于等于根号下当前糖果的数量 且 是它的因数的话
{
dp[i] = max(dp[i],dp[i - * prime[j]] + prime[j]); //求最优解
}
}
} cout<<dp[number];
return ;
}

c++代码:

#include <iostream>
#include <vector>
#include <cmath>

using std::cout;
using std::cin;
using std::vector;
using std::max;

int main()
{
vector<int> prime;
//存放小于等于根号下 number 的所有质数
int number; //等待输入的总糖果数量
bool flag; //状态。判断一个数字是不是质数

cin>>number;
vector<int> dp(number + 1,0); //dp向量。记录当糖果数量为i时能拿的糖果

//求质数,并将所有质数保存到prime中
int sqt1 = sqrt(number);
for(int i = 2; i <= sqt1; ++i)
{
int sqt2 = sqrt(i);
flag = true;
for(int j = 2; j <= sqt2; ++j)
{
if(i % j == 0)
flag = false;
}
if(flag == true)
prime.push_back(i);

}

//处理dp向量
for(int i = 1; i != number + 1; ++i) //i代表dp的下标,代表糖果的数量
{
int sqt2 = sqrt(i);
int _size = prime.size();
for(int j = 0; j != _size; ++j) //遍历整个质数的数组
{
if(prime[j] <= sqt2 && i % prime[j] == 0) //如果这个质数小于等于根号下当前糖果的数量 且 是它的因数的话
{
dp[i] = max(dp[i],dp[i - 2 * prime[j]] + prime[j]); //求最优解
}
}
}

cout<<dp[number];
return 0;
}

DP-动态规划算法实例:拿糖果问题的更多相关文章

  1. 动态规划 算法(DP)

    多阶段决策过程(multistep decision process)是指这样一类特殊的活动过程,过程可以按时间顺序分解成若干个相互联系的阶段,在每一个阶段都需要做出决策,全部过程的决策是一个决策序列 ...

  2. 动态规划算法(Dynamic Programming,简称 DP)

    动态规划算法(Dynamic Programming,简称 DP) 浅谈动态规划 动态规划算法(Dynamic Programming,简称 DP)似乎是一种很高深莫测的算法,你会在一些面试或算法书籍 ...

  3. 从最长公共子序列问题理解动态规划算法(DP)

    一.动态规划(Dynamic Programming) 动态规划方法通常用于求解最优化问题.我们希望找到一个解使其取得最优值,而不是所有最优解,可能有多个解都达到最优值. 二.什么问题适合DP解法 如 ...

  4. 五大常用算法之二:动态规划算法(DP)

    一.基本概念 动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划. 二.基本思想与策略 基本 ...

  5. 剑指Offer——动态规划算法

    剑指Offer--动态规划算法 什么是动态规划? 和分治法一样,动态规划(dynamic programming)是通过组合子问题而解决整个问题的解. 分治法是将问题划分成一些独立的子问题,递归地求解 ...

  6. 多线程动态规划算法求解TSP(Traveling Salesman Problem) 并附C语言实现例程

    TSP问题描述: 旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须 ...

  7. (转)dp动态规划分类详解

    dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间 ...

  8. DP动态规划学习笔记

    作为考察范围最广,考察次数最多的算法,当然要开一篇博客来复习啦. 子曰:温故而知新,可以为师矣 我复习DP时有一些自己对DP的理解,也就分享出来吧. ——正片开始—— 动态规划算法,即Dynamic ...

  9. DP动态规划学习笔记——高级篇上

    说了要肝的怎么能咕咕咕呢? 不了解DP或者想从基础开始学习DP的请移步上一篇博客:DP动态规划学习笔记 这一篇博客我们将分为上中下三篇(这样就不用咕咕咕了...),上篇是较难一些树形DP,中篇则是数位 ...

随机推荐

  1. api中locale或language字段,传送客户端地域信息,一般为下划线

    在请求新闻的分类信息和新闻内容时,需要在api地址中传入local参数,根据用户地区不同返回不同的新闻和分类. local参数,通过navigator.languages[0]获取, 但是,问题来了: ...

  2. 18-10-18 Python 思维导图 很棒的

    赠送 14 张 Python 知识点思维导图   来源 | Python学习联盟 本文主要涵盖了 Python 编程的核心知识(暂不包括标准库及第三方库). 按顺序依次展示了以下内容的一系列思维导图: ...

  3. switfmailer 邮件时间错误 处理

    Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use ...

  4. kbmMW功能#5 - kbmMWProcess单元

    在新的kbmMW v.5.06.20版本中新加kbmMWProcess单元.通过TkbmMWProcess类的各种类方法,可以轻松地在Windows上对外部进程进行分组,启动和停止.在即将发布的小修补 ...

  5. 2--linux命令--查看磁盘空间

    du命令用来查看目录或文件所占用磁盘空间的大小.常用选项组合为:du -sh 二.du常用的选项: -h:以人类可读的方式显示 -a:显示目录占用的磁盘空间大小,还要显示其下目录和文件占用磁盘空间的大 ...

  6. POJO,JaveBean,VO,DTO

    POJO - POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称. 使用POJO名称是为了避免和EJ ...

  7. hdoj-4417(做法二 树状数组离线解法,对所有的查询先保存进行排序后有序的查询) 好腻害!

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std;; ; str ...

  8. 2017-2018-1 20155208 课堂测试(ch06)(补做)

    2017-2018-1 20155208 课堂测试(ch06)(补做) 1.( 多选题 | 1 分) 下面说法正确的是(ABC) A . 存储层次结构中最小的缓存是寄存器 B . 存储层次结构的中心思 ...

  9. C++学习(二十八)(C语言部分)之 文件操作

    复习:#define 定义一个宏#include 文件包含#if 条件防止头文件重复包含定义一个宏 判断宏是否定义 判断头文件是否包含#define _STDIO_H_#include<stdi ...

  10. da shu mo ban

    #include<bits/stdc++.h> using namespace std; ;/*精度位数,自行调整*/ //1.如果需要控制输出位数的话,在str()里面把len调成需要的 ...