您的位置:首页 > 其它

NOJ 1135 Missile dp 最长上升子序列变形 双dp

2016-09-20 16:47 309 查看

Missile

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte

总提交 : 147            测试通过 : 45 


比赛描述

Long , long ago ,country A invented a missile system to destroy the missiles from their enemy . That system can launch only one missile to destroy multiple missiles if the heights of all the missiles form a non-decrease sequence .

But recently , the scientists found that the system is not strong enough . So they invent another missile system . The new system can launch one single missile to destroy many more enemy missiles . Basically , the system can destroy the missile from near
to far . When the system is begun , it chooses one enemy missile to destroy , and then destroys a missile whose height is lower and farther than the first missile . The third missile to destroy is higher and farther than the second missile … the odd missile
to destroy is higher and farther than the previous one , and the even missile to destroy is lower and farther than the previous one .

Now , given you a list of the height of missiles from near to far , please find the most missiles that can be destroyed by one missile launched by the new system .

输入

The input contains multiple test cases .

In each test case , first line is an integer n ( 0<n<=1000 ) , which is the number of missiles to destroy . Then follows one line which contains n integers ( <=109 ) , the height of the missiles followed by distance .

The input is terminated by n = 0 .

输出

       For each case , print the most missiles that can be destroyed in one line .

样例输入

4

5 3 2 4

3

1 1 1

0

样例输出

3

1

题目来源

NUPT ACM

    题意:一种导弹系统,第一次集中第一个目标,下次击中一个比前一个高度小的目标,再下次击中一个比前面高度大的目标,以此循环,问最终能击毁的最大目标数。

    分析:最长上升子序列的变形。最长上升子序列有一种解法:建立数组dp[i],表示以a[i]为末尾的元素的最长上升子序列的最大长度,即每次对每个元素遍历前面的元素 找出a[j]<a[i] j<i 中最大的dp[j] dp[j]=dp[i]+1。理解此法后能帮助理解这一题。该题每一个给出的高度都可以作为“高”目标击中,也可作为"低"目标击中,以da数组表示该数作为高目标被击中时的最大目标数,db数组表示作为低目标击中时的最大目标数,当作为高目标击中的时候,从db数组中选择下标比它小且高度比它小的数,记作db[k],以k作为它的前面一个高度比它小的目标,此时da[i]=db[k]+1,找出所有的k得出最大的da[i]。同理可以得到如果如果a[i]的值小于a[k]则,此时i作为低点,更新db数组。最终遍历得到最大的值即为结果。见AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1005;
long long a[maxn];
int da[maxn],db[maxn];
int main()
{
<span style="white-space:pre">	</span>int n;
<span style="white-space:pre">	</span>while(~scanf("%d",&n),n)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>for(int i=0; i<n; i++)
<span style="white-space:pre">			</span>scanf("%I64d",&a[i]);
<span style="white-space:pre">		</span>memset(da,0,sizeof(da));
<span style="white-space:pre">		</span>memset(db,0,sizeof(db));
<span style="white-space:pre">		</span>da[0]=1;//初始化
<span style="white-space:pre">		</span>db[0]=0;//初始化
<span style="white-space:pre">		</span>for(int i=0; i<n; i++)
<span style="white-space:pre">			</span>for(int j=0; j<i; j++)
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>if(a[j]<a[i])//如果i作为高点  前一个需要比它低
<span style="white-space:pre">					</span>da[i]=max(da[i],db[j]+1);
<span style="white-space:pre">				</span>if(a[j]>a[i])//如果i作为低点  前一个需要比它高
<span style="white-space:pre">					</span>db[i]=max(db[i],da[j]+1);
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>int res=-1;
<span style="white-space:pre">		</span>for(int i=0; i<n; i++)
<span style="white-space:pre">			</span>res=max(res,max(da[i],db[i]));
<span style="white-space:pre">		</span>printf("%d\n",res);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return 0;
}
    特记下,以备后日回顾。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: