题目描述
一种药剂可以被稀释成不同的浓度供病人使用,且只能稀释不能增加浓度;又已知医院规定同一瓶药剂只能给某个病人以及排在他后面的若干人使用。现为了能最大限度利用每一瓶药剂(不考虑每一瓶容量),在给出的一个病人用药浓度序列(病人的顺序不能改变)中找出能同时使用一瓶药剂的最多人数。
关于输入
有两行,第一行是一个整数n,为病人的人数,假设不超过100;第二行为一个浮点数(double)序列,为每个病人的用药浓度,浮点数之间用一个空格隔开。
关于输出
输出一行,该行包含一个整数,为所求的最大人数。
例子输入
6 0.7 0.9 0.6 0.8 0.8 0.4
例子输出
4
优化算法(以找Longest Increasing Subsequence为例)
定义low(i),表示长度为i的LIS中结尾元素的最小值
对于LIS_1, LIS_2,如果LIS_1结尾元素小于LIS_2结尾元素,则能拼接到LIS_2的数一定能拼接到LIS_1,因此我们只需要维护结尾元素的最小值即可。
对于每一个数A[i] :
如果A[ i ] > low[当前最长的LIS长度],就把 A[ i ]接到当前最长的LIS后面,即low[当前最长的LIS长度+1] = A[ i ]
否则,用 A[ i ] 更新 low 数组:在low数组中找到第一个大于等于A[ i ]的元素low [ j ],令low [ j ] = A[ i ]。
由于low是单调递增的,可以进行二分查找
时间复杂度:O(NlogN)
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int n;
double a[100] = {};
double high[100] = {};
int ans = 1;//初始时LDS长度为1
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
high[i] = 99999;
}
high[1] = a[1];
for (int i = 2; i <= n; ++i) {
if (a[i] <= high[ans])//若a[i]<high[ans],直接把a[i]接到后面
high[++ans] = a[i];
else//否则,找到high中第一个<=a[i]的位置high[j],用a[i]更新high[j]
{
for (int j = 1; j <= n; ++j) {
if (high[j] < a[i]) {
high[j] = a[i];
break;
}
}
}
}
cout << ans << endl;
return 0;
}