PAT1030 完美數列(記憶化優化)

 

先上題鏈接:click here

這題剛開始一看排序後無非就是對首部和尾部兩種狀態的操作,於是果斷來一發dfs,然後就各種超時,即使是優化到以下代碼這種優化到極致的代碼,依然超時,卡在第四個測試點。

然後一看N最大爲100000,那麼用dfs時間複雜度爲2^50000,不超時就有了鬼了。。。

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <climits>

using namespace std;

const int MAXN = 100005;
const int INF = INT_MAX;

int p, ans;
int num[MAXN];

void dfs(int start, int end, int step){
	if(step == ans) return;
	if(start > ans) return; 
	if(num[start] >= (double)num[end]/p){
		ans = step;
		//printf("%d %d\n", start, end);
		//printf("%d %d\n", num[start], num[end]);
		return;
	}
	//printf("....\n");
	step++;
	dfs(start+1, end, step);
	dfs(start, end-1, step);
}

int main(){
//	freopen("in.txt", "r", stdin);
	int N;
	while(~scanf("%d %d", &N, &p)){
		ans = INF;
		for(int i = 0; i < N; i++){
			scanf("%d", &num[i]);
		}
		sort(num, num+N);
		dfs(0, N-1, 0);
		printf("%d\n", N-ans);
	}
	return 0;
}

 

後來就想到了常規方法,兩層for時間複雜度爲n^2,找到最大完美數列長度時對小於這個長度的數列不予比較,結果依然各種超時,依舊卡在第四個測試點。

然後我就無奈了,看了題解,發現他們普遍都是在第二層for遍歷時直接跳過了已知的最大完美數列長度,而不是我這種遍歷了不符合才跳過。。。這種做法確實大大節省了時間。。可惜我沒有想到。。能力不足吧。。

話說這題除了第四個測試點都弱爆了,pat的題不常做,可是這種題直接用第四個測試點就好了吧,幹嘛要給人些安慰分呢,做不出來就是做不出來。

 

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <climits>

using namespace std;

const int MAXN = 100005;

int main(){
//	freopen("in.txt", "r", stdin);
	int N, p, num[MAXN], ans;
	while(~scanf("%d %d", &N, &p)){
		ans = 0;
		for(int i = 0; i < N; i++){
			scanf("%d", &num[i]);
		}
		sort(num, num+N);
		for(int i = 0; i < N; i++){
			for(int j = i+ans; j < N; j++){
				if(num[i] < (double)num[j]/p){//不是完美數列 
					ans = j-i;
					break;
				}
				if(j == N-1) ans = N-i;//如果匹配到數列尾部還沒有出現非完美數列元素,則完美數列元素爲當前到尾部 
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章