【 OJ 】 HDOJ1025 18年11月08日19:07 [ 24 ]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QingCoffe/article/details/83866413

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;
}

猜你喜欢

转载自blog.csdn.net/QingCoffe/article/details/83866413