Codeforces Round #570 (Div. 3) F. Topforces Strikes Back
作者:互联网
题目链接:http://codeforces.com/contest/1183/problem/F
题意:现在有n个数,你需要选3个数出来,使3个数的和最大,要求是三个数任意两个做除数和被除数余数不能等于0。
解题心得:看起来n很大,但是可以直接DFS暴力搜索,因为只选三个数所以递归不会超过三层,并且可以剪枝,具体剪枝技巧如下:
- 按从大到小的顺序排列,然后去重。
- 记录当前搜索到的最大值,枚举第一个数的时候,如果3∗第一个数不大于当前记录的最大值直接跳出;枚举第二个数时如果第一个数加上第二个数∗2不大于当前记录的最大值直接跳出;枚举第三个数如果前两个数加上当前枚举的第三个数不大于当前记录的最大值直接跳出。(因为有第一步排序和去重)
#include <bits/stdc++.h>
using namespace std;
typedef complex<double> cp;
typedef long long ll;
const int maxn = 2e5 + 100;
const double pi = acos(-1);
int t, n, num[maxn], Max;
namespace io {//快读板子,好像用不上
const int SIZE = 1e7 + 10;
char inbuff[SIZE];
char *l, *r;
inline void init() {
l = inbuff;
r = inbuff + fread(inbuff, 1, SIZE, stdin);
}
inline char gc() {
if (l == r) init();
return (l != r) ? *(l++) : EOF;
}
void read(int &x) {
x = 0;
char ch = gc();
while (!isdigit(ch)) ch = gc();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
}
}
using io::read;
void init() {
read(n);
for (int i = 1; i <= n; i++) {
read(num[i]);
}
sort(num + 1, num + 1 + n);
reverse(num + 1, num + 1 + n);
n = unique(num+1, num+1+n) - num - 1;
}
void DFS(int num1, int num2, int num3, int pos) {//枚举三个数
if (num1 == -1) {
for (int i = pos; i <= n; i++) {
if (3 * num[i] <= Max) return;//剪枝
if (num[i] > Max) Max = num[i];
DFS(num[i], num2, num3, i + 1);
}
} else if (num2 == -1) {
for (int i = pos; i <= n; i++) {
if (num1 + 2 * num[i] <= Max) return;//剪枝
if (num1 % num[i] == 0) continue;
if (num1 + num[i] > Max) Max = num1 + num[i];
DFS(num1, num[i], num3, i + 1);
}
} else if (num3 == -1) {
for (int i = pos; i <= n; i++) {
if (num1 + num2 + num[i] <= Max) return;//剪枝
if (num1 % num[i] == 0 || num2 % num[i] == 0) continue;
if (num1 + num2 + num[i] > Max) Max = num1 + num2 + num[i];
DFS(num1, num2, num[i], i + 1);
}
}
}
int main() {
//freopen("1.in.txt", "r", stdin);
read(t);
while (t--) {
init();
Max = 0;
DFS(-1, -1, -1, 1);
printf("%d\n", Max);
}
}
标签:ch,int,Max,570,Codeforces,Strikes,init,num,gc 来源: https://blog.csdn.net/yopilipala/article/details/95370266