点击查看代码
/*
给出N个整数(可能有负数),从中选择K个数(可以重复选择),使得K个数的和等于一个给定整数X,如果有多种符合要求的方案时,选择K个数中平方和最大的那个
问题等价于:枚举从N个整数中选择K个数(可以重复选择)的所有方案
例如给出3个整数1、4、7,从中选出5个数使得它们的和为17,可以得到方案{1,1,1,7,7}
*/
#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, nowK + 1, sum + A[index], sumSqu + A[index] * A[index]); //进递归判断选择了第index号数的temp[]是否符合条件,如果符合则比较是否最优
//如果temp[]达不到条件要求,则继续判断是否再选多一次第index号数
//如果temp[]超出条件要求,则出递归返回上一层
//2、不选择第index号数
temp.pop_back(); //将情况1中添加的第index号数从temp[]中删除
DFS(index + 1, nowK, sum, sumSqu); //进递归判断是否选择第index+1号数,第2~4个实参保持不变
}