涉及知識點:列舉,
STL
。
題目大意
給你一個序列,讓你選出一些元素,使其構成 fibonacccccci
數列,求數列的最大長度。
解題思路
定義一個桶,$mp_i$ 代表 $i$ 這個數在輸入序列當中出現的次數。
由於 $n \le 1000$,所以可以直接暴力列舉 fibonacccccci
數列的前兩個數。
前兩個數固定了,這個序列的所有數字都固定了,只需要判斷當前序列的下一個數字可不可以組合出來。
map<int, int> hh;
int cnt = 2;
int now1 = a[i];
int now2 = a[j];
hh[now1]++, hh[now2]++;
while (hh[now1 + now2] < mp[now1 + now2]) {
int t = now1;
now1 = now2;
now2 = t + now2;
hh[now2]++;
cnt++;
}
再來說一下剪枝。
- 如果序列裡包含 $0$,先把 $ans$ 初始化成 $0$ 的個數,這樣就可以防止列舉起點的多餘計算。
- 如果序列包含兩個及以上個 $0$,需要在列舉前兩個數時特判,因為起始兩個 $0$ 的序列全是 $0$,會在第 $1$ 種剪枝當中直接計算出來最優解。
- 如果前一個序列的第 $1$ 個數和這個序列的第 $1$ 個數相同,說明兩個序列是完全一樣的,直接跳過當前序列,計算下一個序列。
最後,統計每個序列長度,取最大值即可。
程式碼
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define il inline
using namespace std;
const int N = 1000 + 10;
int n, a[N];
map<int, int> mp;
int ans;
vector<int> v;
il void Init() {
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
}
il void Solve() {
for (int i = 1; i <= n; i ++ ) mp[a[i]]++;//統計數字出現個數
ans = max(ans, mp[0]);//剪枝1
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ ) {
if (i == j) continue;//起始不能為同一個位置的數
if (a[i] == 0 && a[j] == 0) continue;//剪枝2
if (i > 1 && a[i - 1] == a[i]) break;//剪枝3
map<int, int> hh;//統計當前序列數字出現的個數
int cnt = 2;
int now1 = a[i];
int now2 = a[j];
hh[now1]++, hh[now2]++;
while (hh[now1 + now2] < mp[now1 + now2]) {
int t = now1;
now1 = now2;
now2 = t + now2;
hh[now2]++;
cnt++;//統計當前序列長度
}
ans = max(ans, cnt);//更新答案
}
cout << ans;
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// freopen("fibonacci.in", "r", stdin);
// freopen("fibonacci.out", "w", stdout);
int T = 1;
// cin >> T;
while (T--) {
Init();
Solve();
}
}
透過記錄。