这道题老师说涉及动态规划,(动态规划的水题),可是我连动态规划是啥都不懂...因此第一步先查阅相关资料,了解一下动态规划...
#动态规划
动态规划算法的核心就是记住已经解决过的子问题的解。
什么样的问题可以考虑使用动态规划解决呢?
::如果一个问题,可以把所有可能的答案穷举出来,并且穷举出来后,发现存在重叠子问题,就可以考虑使用动态规划。
需要联系的动态规划习题类型:最长递增子序列、最小编辑距离、背包问题、凑零钱问题
动态规划算法的两种形式:①自顶向下的备忘录法 ②自底向上
算法-动态规划 Dynamic Programming--从菜鸟到老鸟_HankingHu的博客-CSDN博客_动态规划
#动态规划和贪心算法的区别
转载自:(4条消息) 动态规划和贪心算法的区别_Mingsheng Zhang的博客-CSDN博客_动态规划和贪心算法的区别
联系:
都是分解成子问题来求解,都需要具有最优子结构
所有的贪心问题都可以用动态规划来求解,可以这么说,贪心算法是动态规划的特例。
区别:
1.贪心:每一步的最优解一定包含上一步的最优解,上一步之前的最优解则不作保留;
2.动态规划:全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有的局部最优解
#题目:防御导弹
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截 系统有一个缺陷:虽然它的第一发炮弹能够达到任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试 用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入描述
最多20个整数,分别表示导弹依次飞来的高度(雷达给出高度数据是不大于30000的正整数)
输出描述
整数M。表示:这套系统最多能拦截 M 枚导弹.
样例输入
300 250 275 252 200 138 245
样例输出
5
#问题分析(个人理解)
因为动态规划,核心思想包括拆分子问题,记住过往,减少重复计算。
就输入案例来看:
a【0】=1,一个导弹拦截数为1
导弹高度300时,300>250,max=a[0]=1; 第2个导弹发射拦截数a【1】=1+1=2
导弹高度250时,300>275,max=a[0]=1; 250<275不满足条件: 第3个导弹发射拦截数a[2]=1+1=2
导弹高度275时,300>252,max=a[0]=1;250<252不满足条件;275>252 max=a[2]=2; a[3]=1+2=3 第4个导弹发射拦截数
导弹高度252时, 300>200,max=a[0]=1,250>200 max=a[1]=2;275>200 max=a[2]=2;252>200 max=a[3]=3; 第5个导弹发射拦截数 a[4]=3+1=4
导弹高度138时, 300>138,max=a[0]=1,,250>138 max=a[1]=2;275>138 max=a[2]=2;252>138 max=a[3]=3; 200>138 max =a[4]=4 第6个导弹发射 拦截数 a[5]=4+1=5
导弹高度245时,300>245,max=a[0]=1,250>245 max=a[1]=2;275>245 max=a[2]=2;252>245 max=a[3]=3;200<245不满足条件;138<245不满足条件 第7个导弹发射 拦截数 a[6]=3+1=4
上面提到:动态规划算法的核心就是记住已经解决过的子问题的解。
本题子问题的最优解就是a[i]所对应的每颗导弹发射的时候拦截的最大数量,利用子问题的结果计算一颗颗导弹的最大拦截数(个人见解)
相关题目及答案见:(4条消息) 贪心算法之拦截导弹(C++)_西叶胡杨的博客-CSDN博客
#Java代码
本题即是求动态规划的最长下降子序列:
import java.util.Arrays;
import java.util.Scanner;
//防御导弹
public class FangYuDaoDan {
public static void main(String [] args){
Scanner scanner=new Scanner(System.in);
int ddH[]=new int[20];//最多20颗导弹
int n=0;//统计导弹数量
while(scanner.hasNext()){
ddH[n]=scanner.nextInt();
n++;
}
int a[]=new int[n];
//用a【】记录下每颗导弹拦截时的最大颗数
for(int i=0;i<n-1;i++){
a[i]=1;
}
/*
第一颗导弹:初设拦截0颗,判断第一颗导弹拦截最大颗数是否为最优解,并且当前高度>下一颗导弹的高度
即可拦截,可拦截一颗,实际能拦截两颗
*
*/
for(int i=0;i<n-1;i++){
int max=0;
//找出从0到第i颗中拦截系统标记在a数组中最大的值
for(int j=0;j<=i;j++){
if(a[j]>max&&ddH[j]>=ddH[i+1]){
max=a[j];
}
}
//第i+1颗导弹是第max导弹后被拦截,记录第几枚导弹的最大拦截数
a[i+1]=max+1;
}
//给所有拦截数排序
Arrays.sort(a);
System.out.println(a[n-1]);
}
}
新手上路,边学边记;
这算不算动态规划中的自顶向下的备忘录法?