【2014广州市选day1】导弹拦截【蒟蒻的小题解】

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

分析

这题一看就知道是DP了吧?

那么我们设 f [ i ] [ j ] f[i][j] f[i][j]表示到第 i i i个导弹用了 j j j次复原的机会。

那么动态转移方程也就呼之欲出了:

f [ i ] [ k ] = m a x ( f [ i ] [ k ] , f [ j ] [ k ] + 1 ) f[i][k]=max(f[i][k],f[j][k]+1) f[i][k]=max(f[i][k],f[j][k]+1)

f [ i ] [ k + 1 ] = m a x ( f [ i ] [ k + 1 ] , f [ j ] [ k ] + 1 ) f[i][k+1]=max(f[i][k+1],f[j][k]+1) f[i][k+1]=max(f[i][k+1],f[j][k]+1)

这里我们枚 i , j , k i,j,k i,j,k,分别表示枚举到第 i i i个导弹,上一个拦截掉的导弹是第 j j j个,在拦截第 j j j个导弹时用了 k k k次复原机会。

这个方程应该挺简单易懂的吧。。。

CODE

代码~~~~~~~~~~~~~丑!

//L.E.M.T专用水印
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,a[105],f[105][105],ans;
int main() {
    
    
	scanf("%d%d",&m ,&n);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	f[1][0]=1;	
	for (int i=2;i<=n;i++) {
    
    
		for (int j=1;j<=i-1;j++) {
    
    
			for (int k=0;k<=min(m,j-1);k++) {
    
    
				if (a[j]>=a[i]) f[i][k]=max(f[i][k],f[j][k]+1);
				else f[i][k]=max(f[i][k],f[j][k]);
				if (k<m) {
    
    
					f[i][k+1]=max(f[i][k+1],f[j][k]+1);
				}
			}
		}
	}
	ans=0;
	for (int i=0;i<=min(m,n-1);i++) ans=max(ans,f[n][i]);
	printf("%d",ans);
}

解决。

猜你喜欢

转载自blog.csdn.net/qq_49972640/article/details/108548893
今日推荐