联盟周赛2019810 csgo (动态规划、不下降子序列)
今天起晚了...就做了俩题 难受的一批...
题目描述
著名第一人称射击游戏 csgo 因其优秀的平衡性,爽快的射击感和科学的战术配比赢得了世界广大玩家的好评。 在一局游戏中,分为两个阵营,他们的目标就是消灭全部的对方敌人。
现在你是其中的一名玩家,不幸的是,你突然遭遇了许多个站成一横排,身高不同的敌人。
这种时候,用武器瞄准对方的头部进行 “爆头”(一击必杀)是化解险境的唯一方法。
不幸的是,你手中的武器由于过于老旧而后坐力巨大。(而且放浪的你还不喜欢压枪)
也就是说,在一轮扫射中,第一发子弹可以向任意高度水平射出,但是之后每发子弹射出的高度都不能低于前一发子弹射出的高度。(我们假设子弹在飞行中一直沿水平方向飞行,不会下落)
我们假定你无需考虑换弹问题,并且你是一名神枪手,拥有一颗子弹就可以对一个敌人进行“爆头”的能力,不会打空枪 。然而放浪的你有一个坏习惯,就是只喜欢从左向右扫射。
那么为了快速解决掉前方的所有敌人,请问你至少需要进行几轮扫射?
输入格式
本题输入若干组数据,每组数据分为两行。
第一行有一个整数 nnn,表示你面前遇到敌人的数量(1≤n≤100001 \le n \le 10000)
第二行有 n 个整数 hih_i,(1≤hi<MAX_INT1 \le hi< MAX\_INT)表示每个敌人的身高(认为头部的高度等于身高)
输出格式
一个整数,表示最少消灭全部敌人需要的扫射轮数
题目分析
如果当前目标比前面的导弹都低,就必须多开一个导弹,否则更新导弹高度即可
代码
#include<cstdio> #include<cstring> using namespace std; const int maxn=1e6+7; int dp[maxn]; int n,x,cnt; int main() { while(scanf("%d",&n)!=EOF){ memset(dp,0,sizeof(dp)); cnt=0; for(int i=1;i<=n;i++){ scanf("%d",&x); int j; for( j=1;j<=cnt;j++){ if(x>=dp[j]){ dp[j]=x; break; } } if(j>cnt) dp[++cnt]=x; } printf("%d\n",cnt); } return 0; }