ADV205拿糖果(动态规划)

本文探讨了小B如何在特定规则下最大化拿糖果数量的问题。通过动态规划思想,利用质数表优化递归过程,减少了计算量。文章提供了一个完整的Java实现方案,并详细解释了算法的设计与实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

动态规划的思想,设已经拿了n块糖,则最终最多可以拿的糖取决于从剩下的M块糖里,最多可以拿多少糖,则有

solve(M,n)=n+MAX(M)

而MAX(M)=max{solve((M-2*P1)+P1),solve((M-2*P2)+P2),solve((M-2*P3)+P3)….}

所以有solve(M,n)=n+max{solve((M-2*P1)+P1),solve((M-2*P2)+P2),solve((M-2*P3)+P3)….}

求MAX(M)的过程可以在循环中做,最后将MAX(M)的保存在数组里,优化递归,减少运算。
创建一个质数数组表 减少运算量

代码:

import java.util.Scanner;
public class Main
{
    private static final int MAX=100000;
    private static int[] prime=new int[10000];
    private static int[] max=new int[MAX];
    private static int pSize=0;
    public static  void creatPrime(int n)
    {
        prime[pSize++]=2;
        for(int i=3;i<Math.sqrt(n);i++)
        {
            boolean flag=true;
            for(int j=2;j<=Math.sqrt(i)+1;j++)
            {
                if (i%j==0)
                { 
                    flag=false;
                    break;
                }
            }
            if(flag)
                prime[pSize++]=i;
        }
    }

    public static int solve(int m,int n)
    {
        if(max[m]>=0)
            return max[m]+n;
        int t=0,MAX=0;
        for(int i=0;i<pSize;i++)
        {
            if(prime[i]>Math.sqrt(m))
                break;
            if( m%prime[i]==0)
            {
                t=solve(m-2*prime[i],prime[i]);
                if(t>MAX)
                    MAX=t;
            }
        }
        max[m]=MAX;
        return MAX+n;
    }
    public static void main(String[] args) 
    {
        Scanner cin=new Scanner(System.in);
        int n=cin.nextInt();

        //初始化max数组
        for(int i=0;i<max.length;i++)
            max[i]=-1;
        max[0]=0;max[1]=0;max[2]=0;max[3]=0;

        //生成质数表
        creatPrime(n);

        System.out.println(solve(n, 0));

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值