先上題鏈接: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;
}