【2014广州市选day1】JZOJ2020年9月12日提高B组T2 导弹拦截

【2014广州市选day1】JZOJ2020年9月12日提高B组T2 导弹拦截

题目

Description

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统 V1.0。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够达到任意的高度,但是以后每一发炮弹都不能高于前一发的高度,这样会大大降低导弹的拦截率。
经过技术人员的苦心改良,导弹拦截系统升级为 V2.0,使得这个拦截系统在拦截过程中,有若干次机会提升到任意高度,虽然次数有限,但是已经算很大的改进了。
某天,雷达捕捉到敌国的导弹来袭,导弹 V2.0拦截系统接受考验的时刻开始来临了。

Input

第一行为整数N (0<=N<=20),M(1<=M<=50),N代表导弹拦截系统在拦截过程中,可以提升到任意高度的次数;M代表需要拦截的导弹的数目。N、M两个整数用空格隔开。
第二行为M个正整数,每个整数间使用若干空格隔开,分别表示导弹依次飞来的高度,雷达给出高度数据是不大于1000的正整数。

Output

输出一个正整数,代表该导弹拦截系统最多可以拦截的导弹数目。

Sample Input

1 7
300 250 275 252 200 138 245

Sample Output

6

题解

题意

给出一个导弹拦截系统
第一发可以打到任意高度,但之后每一次都要低于前一次
n n n次机会可以上升到任意高度
问在 m m m个导弹里最多可以拦截多少个

分析

DP模板题导弹拦截升级版
一样是采取DP的方式
只不过有些不同
f [ i ] [ j ] f[i][j] f[i][j]表示当前是第 i i i个导弹,用了 j j j次提升高度
那么转移显然

  • 当可以直接打到时 f [ i ] [ j ] = m a x ( f [ i ] [ j ] , f [ i − 1 ] [ j ] + 1 ) f[i][j]=max(f[i][j],f[i-1][j]+1) f[i][j]=max(f[i][j],f[i1][j]+1)
  • 当可以是使用提升高度时 f [ i ] [ j + 1 ] = m a x ( f [ i ] [ j + 1 ] , f [ i − 1 ] [ j ] + 1 ) f[i][j+1]=max(f[i][j+1],f[i-1][j]+1) f[i][j+1]=max(f[i][j+1],f[i1][j]+1)

注意的是 f [ i ] [ j ] f[i][j] f[i][j]的初值是 m a x ( f [ i − 1 ] [ j ] ) max(f[i-1][j]) max(f[i1][j])

Code

#include<bits/stdc++.h>
using namespace std;
int n,m,ans,a[55],f[55][25];
int read()
{
	int res=0;char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch-'0'),ch=getchar();
	return res;
}
int main()
{
	freopen("missile.in","r",stdin);
	freopen("missile.out","w",stdout);
	m=read();n=read();
	for (int i=1;i<=n;++i)
		a[i]=read();
	f[1][0]=f[1][1]=1;
	for (int i=2;i<=n;++i)
		for (int j=0;j<=min(i,m);++j)
		{
			f[i][j]=max(f[i][j],f[i-1][j]);
			if (a[i]<=a[i-1])
			{
				f[i][j]=max(f[i-1][j]+1,f[i][j]);
				if (j+1<=m) f[i][j+1]=max(f[i-1][j]+1,f[i][j+1]);
			}
			else if (j+1<=m) f[i][j+1]=max(f[i-1][j]+1,f[i][j+1]);
		}
	for (int i=1;i<=n;++i)
		for (int j=0;j<=m;++j)
			ans=max(ans,f[i][j]);
	printf("%d\n",ans);
	fclose(stdin);fclose(stdout);
	return 0;
}
©️2020 CSDN 皮肤主题: 点我我会动 设计师:上身试试 返回首页