思路:
首先,一条火车道可以停很多俩火车
我们需要尽量减少加轨道条数,也就是新的火车最好能到一条路线的末尾排着,而为了之后的顺序输出,一条轨道上后面的车需要比前面的编号小,这就产生了选择问题。选择时可以归结出以下逻辑:
选择时要减少轨道条数,增加轨道条数的条件是需要进入的火车大于所有链尾序号,所以为了减小这个条件的成立可能性,就需要使每条轨道尽量多地容纳。举个例子,比如我们现在有两条轨道,轨道上的链尾为轨道一:5号,轨道二:8号,我们需要插入4号车,如果将4号插入轨道二,轨道二上4到8之间的插入可能性就被夺取了,同等条件下,将4号插入5号,相当于没有夺取其他任何可插入的可能性。而我们的目的就是增大可以不加轨道条数的可能性(等价于增大链尾能插入的可能性,又等价于增大链尾能插入的数量),所以需要做的是将新的元素插入到与这个元素序号差别最小的链尾。
采用二分查找能减少啊时间复杂度,如果暴力查找会部分超时!
具体看代码~~
二分查找
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n;
int a[10010];
cin >> n;
int k, len = 0;
while (n--)
{
cin >> k;
if (len == 0 || a[len - 1] < k)
{
a[len++] = k;
}
else
{
int l = 0;
int r = len - 1;
while (l < r)//二分查找
{
int mid = l + (r - l) / 2;
if (a[mid] > k)
r = mid - 1;
else
l = mid + 1;
}
a[l] = k;
}
}
cout << len;
system("pause");
return 0;
}
暴力查找
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<limits.h>
using namespace std;
int n;
int che[100005];//用于存取链尾序号
int N;
int num=1;
int foun(int n)
{
if (n > che[num])//插不入
return 0;
if (n<che[num] && n>che[num - 1])//如果刚好是在最后一条上
return num;
for (int i = 1; i <= num; i++)
{
if (n < che[i])//检查能否插入
return i;
}
}
int main()
{
cin >> N;
int a;
memset(che, 0, sizeof(che));
che[1] = INT_MAX;
for (int i = 1; i <= N; i++)
{
cin >> n;
if (a=foun(n))//a为火车路的编号
{
che[a] = n;//更新链尾序号
}
else
{
num++;
che[num] = n;//新加一条火车路
}
}
cout << num;
system("pause");
return 0;
}