点击查看代码
/*
给出N个整数(可能有负数),从中选择K个数(不能重复选择),使得K个数的和等于一个给定整数X,如果有多种符合要求的方案时,选择K个数中平方和最大的那个
问题等价于:枚举从N个整数中选择K个数(不能重复选择)的所有方案
输入样例:
4 2 6 //给定4个整数,从中选择2个数,使得它们的和为6
2 3 3 4 //4个数分别是2 3 3 4
输出样例2:
2 4 //元素和等于6的方案有2个:{3,3}和{2,4},而第2个方案的平方和最大
*/
#include<cstdio>
#include<vector>
using namespace std;
#pragma warning(disable:4996)
const int maxn = 100010; // 序列A中最多有10^5个数
int A[maxn], n, k, x, maxSumSqu = -1; //从序列A中n个数选出k个数,使得它们的和为x,最大平方和为maxSumSqu
vector<int> temp, ans; //temp存储当前已选整数的序列,ans存储能得到最大平方和的序列
//当前处理index号整数,当前已选整数个数nowK,当前已选整数的和为sum,当前已选整数的平方和为sumSqu
void DFS(int index, int nowK, int sum, int sumSqu) {
if (nowK == k && sum == x) { //找到k个数的和为x
if (sumSqu > maxSumSqu) { //如果当前已选整数的平方和sumSqu大于maxSumSqu
maxSumSqu = sumSqu; //更新最大平方和
ans = temp; //更新最大平方和的序列
}
return; //出递归返回上一层
}
//已经处理完n个数,或者超过k个数,或者和超过x,此时肯定不会有符合条件的序列,可以直接出递归返回上一层
if (index == n || nowK > k || sum > x) return;
//对于第index号整数,它有2种情况:
//1、选择第index号数(注意第2~4个实参要加上选了第index号后的数据)
temp.push_back(A[index]); //将它放入temp[]中
DFS(index + 1, nowK + 1, sum + A[index], sumSqu + A[index] * A[index]); //进递归判断选择了第index号数的temp[]是否符合条件,如果符合则比较是否最优
//如果temp[]达不到条件要求,则继续判断是否选择第index+1号数
//如果temp[]超出条件要求,则出递归返回上一层
//2、不选择第index号数
temp.pop_back(); //将情况1中添加的第index号数从temp[]中删除
DFS(index + 1, nowK, sum, sumSqu); //进递归判断是否选择第index+1号数,第2~4个实参保持不变
}