导弹拦截

上个大周我居然忘写博客了这里写图片描述,据说再不写我就要爆炸了,所以赶紧来补一篇。
好吧我们第二次学动态规划,上次听过就忘得差不多了,隔了两天我终于把我上次欠下的题给A掉了。

导弹拦截

//怎么样是不是感觉很熟,没错,DP入门题之一。鉴于大家都知道,所以在此不附题目。

主要思路

首先,从题目中以后的每一发炮弹都不能高于前一发的高度我们不难看出,这题的第一问是最长不上升子序列。我们设一个f数组,用来表示拦截到第i发炮弹时已经拦截的炮弹数量,如果第j个导弹比第i个要低的话,就说明前面肯定没有拦截到第j个,于是我们就可以从第一个到第i-1个中进行枚举,选择在第j个之前的f中最大的数值,然后加上自身,则可得到到第j个元素时的最长不上升子序列,然后在f中从1到n进行枚举,就能得到整串数字的最长上升子序列,即第一问。

第二问老师讲的是贪心算法,即从第i个元素前的i-1个元素中,选择最接近但大于第i个元素的元素与其分为一组,以此类推,得到最少分组,再减去1即为第二问所求。但是我觉得代码实现有点……所以我听了同桌的意见,第二问其实可以看做最长上升子序列,与上一问类似,改变判断条件即可,如代码所示。

代码如下

#include
using namespace std;
int main()
{
    int n,a[201],f[210]={},maxx1=0,maxx2=0,t[210]={};
    cin>>n;
    for(int i=1;i<=n;i++)
     cin>>a[i];
    f[1]=1;//我们需要从第二个元素开始比较,所以要先将f[1]定义为1
    for(int i=2;i<=n;i++)
    {
     for(int j=1;jif(a[j]>=a[i]&&f[j]>f[i]) f[i]=f[j];//将每一个元素与其前面的元素比较,并选择之前的最长上升子序列
     f[i]++;//累加自身
    }
    for(int i=1;i<=n;i++)//在n个f[i]中寻找最长上升子序列为本题答案
     if(f[i]>maxx1)
      maxx1=f[i];
    t[1]=1;//与上一问基本相同,求最长上升子序列
    for(int i=2;i<=n;i++)
     {
        for(int j=1;j<=i;j++)
         if(a[i]>a[j]&&t[i]//将第一问中判断a[j]>=a[i]变为a[i]>a[j]
        t[i]++;
     }
    for(int i=1;i<=n;i++)
     if(t[i]>maxx2)
      maxx2=t[i];
    cout<cout<return 0;
}

注意

依旧是细节,本人因为没有给t[1]赋值,第一次只拿了60分~所以,细节决定成败啊~

你可能感兴趣的:(导弹拦截)