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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值