问题
给定一组n个正整数,将它们分成k个子集,然后最小化每个子集和的平方和。例如,设集合为[1,2,3],k为2,则解为[1,2]和[3]。第一个子集的和的平方是(1+2)^2=9,第二个子集的和的平方是3^2=9。和是9+9=18,这是最小值。
输入示例
n=10,k=2 [63230795,3521578,37513838,37860789,30498450,29795141,41263743,5815341,19046274,20919844] -> 41895269854617569
n=10,k=5 [42566460,61080136,12375813,29881559,61767889,60645182,22105410,17262225,34309213,38950048] -> 29098109328960071
约束
- 1≤N≤20
- 1≤K≤10
- 集合中的数字都是正数。您需要使用uint64_t进行算术运算。
我的代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include <stdint.h>
bool used[20] = {0};
int n, m;
uint64_t arr[20], min = UINT64_MAX;
int find(int nset, uint64_t sum);
int subset(uint64_t subsum, int cur, int sum, int nset){
if (cur == n){
find(nset+1, sum+subsum*subsum);
return 0;
}
subset(subsum, cur+1, sum, nset);
if (!used[cur]){
used[cur] = 1;
subset(subsum+arr[cur], cur+1, sum, nset);
used[cur] = 0;
}
return 0;
}
int find(int nset, uint64_t sum){
if (sum >= min)
return 0;
if (nset == m-1){
uint64_t setsum = 0;
for (int i = 0; i < n; i++)
if (!used[i])
setsum += arr[i];
sum += setsum*setsum;
if (sum < min)
min = sum;
return 0;
}else{
subset(0, 0, sum, nset);
return 0;
}
}
int main(){
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++)
scanf("%llu", &arr[i]);
uint64_t z = 0;
find(0, z);
printf("%llu", min);
}
字符串
我的想法是使用残酷的搜索,计算一个子集的平方和和下一个简单的修剪时,当前的解决方案是大于当前的答案,但错误的。我丢了什么东西吗?谢谢你的回答。
3条答案
按热度按时间ee7vknir1#
对于蛮力方法,您首先必须找到 n 的所有 k 个分区。10的所有2个分区是{{9,1},{8,2},{7,3},{6,4},{5,5}}。10的所有5个分区是{{6,1,1,1},{5,2,1,1},{4,3,1,1},{4,2,2,1,1},{3,3,2,1,1},{3,2,2,2,1},{2,2,2,2}}。这些可以用一个简单的递归函数生成。
对于每个分区,用这些分区生成所有唯一子集,并测试它们是否为目标函数的最小值。例如,对于{4,2,2,1,1},从4开始,生成所有10!f(4!6!)= 210个4的子集。在每种情况下,剩下的6个元素都可以生成所有6个!f(2!2!2!2!)= 45个唯一的2的子集对。剩下的2个分别放在剩下的两个1插槽中。然后总共有210*45 = 9450个排列要测试该分区。
10的所有7个5分区的排列总数仅为42525。对于10的所有五个2分区,存在511个布置。然后,所给出的示例很容易服从这种蛮力方法。虽然我怀疑有一个更经济的搜索解决方案,这将更适合于更大的向量,其中安排的数量将呈指数增长。
答案是:
字符串
和/或
型
mkh04yzy2#
我试着自己写一个解决方案,我想出了这个。
字符串
结果与预期的结果不符。但我希望它仍然能帮助你。
iyzzxitl3#
溶胶
字符串
最后,我想出了解决办法。这个想法是试图将每个元素分布到每个子集。同样,用一些“切割”来减少搜索树。这里的“切割”是子集的总和越接近平均值,最小值越小。此外,情况具有的子集越多,最小值越小。所以一旦发现一个子集没有元素,函数就直接返回。这些都是我的观察,我不确定是否所有类似的问题都是如此。希望有人能证实我的想法。- 谢谢-谢谢