ADV205拿糖果(动态规划)

来源:互联网 发布:java怎么以分数形式 编辑:程序博客网 时间:2024/05/29 02:38

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));    }}
原创粉丝点击