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

 

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