ummmm ,题目还是很好理解的,道路只要不交叉就可以了,那么很显然只要r(富裕)城市一直保持递增就好了,因为p(贫穷)城市是正常的123...n 的递增排列
首先拿到这题第一思路就是DP:
数组都开的比较小,因为题目50W的城市时间复杂度稳挂....
然后现在....去看别人代码学习.....二分之类的O(nlogn)
ummmm
# include<iostream>
using namespace std;
int p[100];
int r[100];
int dp[100];
void Out(int n,int sum) {
cout << "Case " << n << ":" << endl;
cout << "My king, at most " << sum << " road can be built."<<endl;
}
int main(void) {
int n;//城市数目
int out_time = 1;
bool ISok = true;
while (cin >> n) {
if (!ISok) {
cout << endl;
ISok = false;
}
for (int i = 0; i < n; ++i) {
cin >> p[i] >> r[i];//先p后r
}//录入数据
dp[0] = 1;
for (int i = 1; i < n; ++i) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (r[i] > r[j]&&dp[i]<=dp[j]) {
dp[i] = dp[j] + 1;
}
}
}//dp处理
int max=0;
for (int i = 0; i < n; ++i) {
if (dp[i] > max)
max = dp[i];
}
Out(out_time++, max);
ISok = false;
}
system("pause");
return 0;
}
转载请注明原文地址:https://www.cnblogs.com/GodA/p/5180560.html
这个讲解的感觉带着实例好理解一点....
我们举一个例子:有以下序列A[]=3 1 2 6 4 5 10 7,求LIS长度。
我们定义一个B[i]来储存可能的排序序列,len为LIS长度。我们依次把A[i]有序地放进B[i]里。(为了方便,i的范围就从1~n表示第i个数)
A[1]=3,把3放进B[1],此时B[1]=3,此时len=1,最小末尾是3
A[2]=1,因为1比3小,所以可以把B[1]中的3替换为1,此时B[1]=1,此时len=1,最小末尾是1
A[3]=2,2大于1,就把2放进B[2]=2,此时B[]={1,2},len=2
同理,A[4]=6,把6放进B[3]=6,B[]={1,2,6},len=3
A[5]=4,4在2和6之间,比6小,可以把B[3]替换为4,B[]={1,2,4},len=3
A[6]=5,B[4]=5,B[]={1,2,4,5},len=4
A[7]=10,B[5]=10,B[]={1,2,4,5,10},len=5
A[8]=7,7在5和10之间,比10小,可以把B[5]替换为7,B[]={1,2,4,5,7},len=5
最终我们得出LIS长度为5。但是,但是!!这里的1 2 4 5 7很明显并不是正确的最长上升子序列。是的,B序列并不表示最长上升子序列,它只表示相应最长子序列长度的排好序的最小序列。这有什么用呢?我们最后一步7替换10并没有增加最长子序列的长度,而这一步的意义,在于记录最小序列,代表了一种“最可能性”。假如后面还有两个数据8和9,那么B[6]将更新为8,B[7]将更新为9,len就变为7。读者可以自行体会它的作用。
我的代码没有AC显示.Time Limit Exceeded 吐血= =~
# include<iostream>
#include <algorithm>
using namespace std;
int p[500002];//规模不超过50W
int r[500002];
int sq[500002];//需要维护的数组
void Out(int n, int sum) {
cout << "Case " << n << ":" << endl;
cout << "My king, at most " << sum << " road"<<((sum>1)?"s":"")<<" can be built." << endl<<endl;
}
//贪心+二分 时间复杂度O(nlogn) 二分用STL中的lowder_bound 实现
int main(void) {
int n;//城市数目
int index;
int time = 0;
while (cin >> n) {
time++;
index = 0;
fill(sq, sq + n, 0);
for (int i = 0; i < n; ++i) {
cin >> p[i] >> r[i];//先p后r
}//录入数据
sq[index] = r[0];
for (int i = 1; i < n; i++) {
if (r[i] >= sq[index]) {
sq[++index] = r[i];//比他大就继承
}
else {
*lower_bound(sq, sq + index+1, r[i])=r[i];//从sq到sq+n 二分查找第一个大于或等于r[i]的数,返回地址赋值r[i]
}
}
Out(time, index+1);
}
system("pause");
return 0;
}