不降原则(用于去重)
![](https://img-blog.csdnimg.cn/img_convert/81891000bff8154df6220dd1b9f3412a.png)
如上题,为了保证搜索选数不会重复,我们要采用不降原则
void dfs(int m, int sum, int startx){ // *** start ***
if(m == k){
if(isprime(sum))
ans++;
return ;
}
for(int i = startx; i < n; i++) // *** i=start ***
dfs(m + 1, sum + a[i], i + 1); // *** i+1 ***
return ;
}
记忆化搜索
条件:在搜索过程中,又出现重复计算的部分
作用:记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,
以后再次遇到这个状态的时候,就不必重新求解了,减少时间花销
![](https://img-blog.csdnimg.cn/img_convert/48d64df3f92c3e0c244ce563ed7afeb1.png)
如上题,每次搜索的状态可以用数组
rpt
[i][j][k]来记录
枚举搜索的优化
题目为了找最大值,为了优化枚举算法,答案从大到小进行搜索,若找到足够大的答案后,后面将要搜索的答案统一跳过
#include<iostream>
#include<queue>
#include<string>
#include<algorithm>
#define MAXN 250050
#define ll long long
using namespace std;
int main(){
ll n, k, a[100050];
cin >> n >> k;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1); // 排序,为了从大到小搜索
ll ans = 0;
for (int i = n; i >= 3; i--) {
for (int j = i - 1; j >= 2; j--) {
for (int m = j - 1; m >= 1; m--) {
ll sum = a[i] + a[j] + a[m];
if (sum < ans) break; // a[i] + a[j] + a[j - 1]是当前m循环内的最大值,若比已找到的答案要小,跳过该循环
if (sum % k == 0) {
ans = max(ans, sum);
}
}
if (a[i] + a[j] + a[j - 1] < ans)break; // a[i] + a[j] + a[j - 1]是当前j循环内的最大值,若比已找到的答案要小,跳过该循环
}
if (a[i] + a[i-1] + a[i - 2] < ans)break; // a[i] + a[j] + a[j - 1]是当前i循环内的最大值,若比已找到的答案要小,跳过该循环
}
cout << ans;
return 0;
}