1. 程式人生 > >PAT-乙-1030 1030 完美數列 (25 分)

PAT-乙-1030 1030 完美數列 (25 分)

在這裡插入圖片描述

程式碼

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {

	int N;
	long long p;
	scanf("%d %ld", &N, &p);

	vector<double> v;
	for(int i=0; i<N; i++) {
		double t;
		scanf("%lf", &t);
		v.push_back(t);
	}

	sort(v.begin(), v.end());

	int maxLen = 1;
	for(int i=v.size()-1; i>=0; i--) {
		if(i+1<=maxLen) {
			break;
		}
		double min = v.at(i)/p;
		int tmpLen = maxLen;
		for(int j=i-maxLen; j>=0; j--) {
			if(v.at(j)<min) {
				break;
			} else {
				tmpLen++;
			}
		}
		if(tmpLen>maxLen) {
			maxLen = tmpLen;
		}
	}

	printf("%d\n", maxLen);

	return 0;
}

註解

1、暴力法:排序後,從最後一個元素開始,依次找每個元素的完美數列所包含的元素個數。這樣可得22分,案例4超時。 2、優化的方法:主要是下面這段程式碼

int maxLen = 1;
    	for(int i=v.size()-1; i>=0; i--) {
    		if(i+1<=maxLen) {
    			break;
    		}
    		double min = v.at(i)/p;
    		int tmpLen = maxLen;
    		for(int j=i-maxLen; j>=0; j--) {
    			if(v.at(j)<min) {
    				break;
    			} else {
    				tmpLen++;
    			}
    		}
    		if(tmpLen>maxLen) {
    			maxLen = tmpLen;
    		}
    	}

(1)如果當前元素所處位置,剩餘的元素只有maxLen個,那麼無論如何也不會超過當前的maxLen的結論,就可以終止迴圈,輸出結果了。這樣大大減少了無謂的判斷次數。 (2)類似於字串匹配KMP的思想,**若當前找到的maxLen為m,則下次不需要再從頭開始比較,只需要從當前位置往前挪m個元素,看是否滿足題目要求。**若滿足,說明有可能達到更長的序列,則繼續前移,否則不滿足,繼續試探下一個元素。這樣就跳過了很多元素的比較,大大節約時間。

3、學到的語法: (1)對vector排序:

#include <vector>
#include <algorithm>
vector<double> v;
sort(v.begin(), v.end());

結果

在這裡插入圖片描述