1. 程式人生 > >【 OJ 】 HDOJ1025 18年11月08日19:07 [ 24 ]

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

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