project euler 103
2015-12-26 01:28
225 查看
Special subset sums: optimum
Let S(A) represent the sum of elements in set A of size n. We shall call it a special sum set if for any two non-empty disjoint subsets, B and C, the following properties are true:
S(B) ≠ S(C); that is, sums of subsets cannot be equal.
If B contains more elements than C then S(B) > S(C).
If S(A) is minimised for a given n, we shall call it an optimum special sum set. The first five optimum special sum sets are given below.
n = 1: {1}
n = 2: {1, 2}
n = 3: {2, 3, 4}
n = 4: {3, 5, 6, 7}
n = 5: {6, 9, 11, 12, 13}
It seems that for a given optimum set, A = {a1, a2,
… , an}, the next optimum set is of the form B = {b, a1+b,
a2+b, … ,an+b}, where b is the “middle”
element on the previous row.
By applying this “rule” we would expect the optimum set for n = 6 to be A = {11, 17, 20, 22, 23, 24}, with S(A) = 117. However, this is not the optimum set, as we have merely applied an algorithm to provide a near optimum set. The optimum set for n = 6 is A
= {11, 18, 19, 20, 22, 25}, with S(A) = 115 and corresponding set string: 111819202225.
Given that A is an optimum special sum set for n = 7, find its set string.
NOTE: This problem is related to Problem
105 and Problem
106.
特殊的子集和:最优解
记S(A)是大小为n的集合A中所有元素的和。若任取A的任意两个非空且不相交的子集B和C都满足下列条件,我们称A是一个特殊的和集:
S(B) ≠ S(C);也就是说,任意子集的和不相同。
如果B中的元素比C多,则S(B) > S(C)。
对于给定的n,我们称使得S(A)最小的集合A为最优特殊和集。前5个最优特殊和集如下所示。
n = 1: {1}
n = 2: {1, 2}
n = 3: {2, 3, 4}
n = 4: {3, 5, 6, 7}
n = 5: {6, 9, 11, 12, 13}
似乎对于一个给定的最优特殊和集A = {a1, a2,
… , an},下一个最优特殊和集将是B = {b, a1+b, a2+b,
… ,an+b}的形式,其中b是集合A“正中间”的元素。
应用这条“规则”,我们猜测对于n = 6的最优特殊和集将是A = {11, 17, 20, 22, 23, 24},相应的S(A) = 117。然而,事实并非如此,我们的方法仅仅只能找出近似最优特殊和集。对于n = 6,最优特殊和集是A = {11, 18, 19, 20, 22, 25},相应的S(A) = 115,对应的集合数字串是:111819202225。
若集合A是n = 7时的最优特殊和集,求其对应的集合数字串。
注意:此题和第105题及第106题有关。
Let S(A) represent the sum of elements in set A of size n. We shall call it a special sum set if for any two non-empty disjoint subsets, B and C, the following properties are true:
S(B) ≠ S(C); that is, sums of subsets cannot be equal.
If B contains more elements than C then S(B) > S(C).
If S(A) is minimised for a given n, we shall call it an optimum special sum set. The first five optimum special sum sets are given below.
n = 1: {1}
n = 2: {1, 2}
n = 3: {2, 3, 4}
n = 4: {3, 5, 6, 7}
n = 5: {6, 9, 11, 12, 13}
It seems that for a given optimum set, A = {a1, a2,
… , an}, the next optimum set is of the form B = {b, a1+b,
a2+b, … ,an+b}, where b is the “middle”
element on the previous row.
By applying this “rule” we would expect the optimum set for n = 6 to be A = {11, 17, 20, 22, 23, 24}, with S(A) = 117. However, this is not the optimum set, as we have merely applied an algorithm to provide a near optimum set. The optimum set for n = 6 is A
= {11, 18, 19, 20, 22, 25}, with S(A) = 115 and corresponding set string: 111819202225.
Given that A is an optimum special sum set for n = 7, find its set string.
NOTE: This problem is related to Problem
105 and Problem
106.
特殊的子集和:最优解
记S(A)是大小为n的集合A中所有元素的和。若任取A的任意两个非空且不相交的子集B和C都满足下列条件,我们称A是一个特殊的和集:
S(B) ≠ S(C);也就是说,任意子集的和不相同。
如果B中的元素比C多,则S(B) > S(C)。
对于给定的n,我们称使得S(A)最小的集合A为最优特殊和集。前5个最优特殊和集如下所示。
n = 1: {1}
n = 2: {1, 2}
n = 3: {2, 3, 4}
n = 4: {3, 5, 6, 7}
n = 5: {6, 9, 11, 12, 13}
似乎对于一个给定的最优特殊和集A = {a1, a2,
… , an},下一个最优特殊和集将是B = {b, a1+b, a2+b,
… ,an+b}的形式,其中b是集合A“正中间”的元素。
应用这条“规则”,我们猜测对于n = 6的最优特殊和集将是A = {11, 17, 20, 22, 23, 24},相应的S(A) = 117。然而,事实并非如此,我们的方法仅仅只能找出近似最优特殊和集。对于n = 6,最优特殊和集是A = {11, 18, 19, 20, 22, 25},相应的S(A) = 115,对应的集合数字串是:111819202225。
若集合A是n = 7时的最优特殊和集,求其对应的集合数字串。
注意:此题和第105题及第106题有关。
package projecteuler; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import junit.framework.TestCase; public class Prj103 extends TestCase { List<int[]> resultList = new ArrayList<int[]>(); /** * simple dfs; * search start from n-1; * k + (k + 1) > k + n -1 */ public void testSpecialSubsetSumsOptimum() { int[] arr = new int[7]; dfs(arr, 0, arr.length - 1, 50 ); System.out.println("size=" + resultList.size()); int sum = Integer.MAX_VALUE; int minId = 0; for( int i = 0 ; i < resultList.size() ; i ++){ int[] _val = resultList.get(i); int val = sumArr(_val); if( val < sum){ sum = val; minId = i; } } printArr(resultList.get(minId)); System.out.println("sum=" + sumArr(resultList.get(minId)) ); } public void dfs(int[] arr, int id, int start, int end) { if (id >= arr.length) { if (checkOk(arr)) { resultList.add(Arrays.copyOf(arr, arr.length)); printArr(arr); } return; } for (int i = start; i <= end; i++) { if (id == 0) { arr[id] = i; dfs(arr, id + 1, start, end); } else { if (i <= arr[id - 1]) { continue; } arr[id] = i; dfs(arr, id + 1, start, end); } } } int sumArr(int arr[]) { int sum = 0; for (int val : arr) { sum += val; } return sum; } private boolean checkOk(int[] arr) { if (Arrays.equals(arr, new int[] { 11, 18, 19, 20, 22, 25 })) { System.out.println(); } assert (arr.length >= 5); int n = arr.length; int sumAsc = arr[0] + arr[1]; int sumDesc = arr[n - 1]; int count = 3; int c = 2; while (true) { if (count > n) { break; } if (sumAsc <= sumDesc) { return false; } sumAsc += arr[c]; sumDesc += arr[n - c]; c++; count += 2; } Set<Integer> set = new HashSet<Integer>(); int sum = 0; for (int val : arr) { set.add(val); sum += val; } set.add(sum); for (int p = 2; p <= n / 2; p++) { Comb cb = new Comb(n, p); List<int[]> cbs = cb.calculateComb(); for (int i = 0; i < cbs.size() - 1; i++) { int[] _cb = cbs.get(i); int sum1 = 0; int sum2 = 0; for (int j = 0; j < _cb.length; j++) { if (_cb[j] == 1) { sum1 += arr[j]; } else { sum2 += arr[j]; } } if (set.contains(sum1)) { return false; } set.add(sum1); if (p == n / 2 && n % 2 == 0) { continue; } if (set.contains(sum2)) { return false; } set.add(sum2); } } return true; } void printArr(int[] diff) { for (int i = 0; i < diff.length; i++) { System.out.print(diff[i] + "\t," ); } System.out.println(); } /** * 组合 * * @author suc * */ public static class Comb { private int n; private int p; public Comb(int n, int p) { this.n = n; this.p = p; } public List<int[]> calculateComb() { assert (p < n && p > 0); List<int[]> ret = new ArrayList<int[]>(); int[] arrs = new int ; for (int i = 0; i < p; i++) { arrs[i] = 1; } ret.add(Arrays.copyOf(arrs, arrs.length)); for (;;) { boolean find = findNext(arrs); ret.add(Arrays.copyOf(arrs, arrs.length)); if (!find) { break; } } return ret; } private boolean findNext(int[] arrs) { int count = 0; int find = -1; for (int i = 0; i < arrs.length - 1; i++) { if (arrs[i] == 1) { count++; } if (arrs[i] == 1 && arrs[i + 1] == 0) { int tmp = arrs[i + 1]; arrs[i + 1] = arrs[i]; arrs[i] = tmp; find = i; break; } } count--; for (int i = 0; i < find; i++) { if (i < count) { arrs[i] = 1; } else { arrs[i] = 0; } } return !(find == -1); } } }
相关文章推荐
- 计算兔子繁殖,斐波那契数列!
- 创建一个类的实例,修改类中定义为private的变量的值
- 小猪的数据结构辅助教程——2.7 线性表中的双向循环链表
- openwrt下安装lighttpd/webdav模块及改变安装目录
- 8天学通MongoDB——第八天 驱动实践
- 数据分析
- 8路监控音频怎么接
- 用递归计算阶乘!
- cf 教育场4 ,区间交集个数
- [看书日记20151226]MeasureSpec和LayoutParams的对应关系 , View的工作流程
- Android逆向工程101 – Part 2
- xUtils3框架
- 简易打折,输入数量金额然后计算打折
- 跳转点寻路介绍
- hdu 1248 寒冰王座
- ImageView xml错误
- android-Distributing to Specific Screens
- 2015年12月25日回顾
- 8天学通MongoDB——第七天 运维技术
- Golang之bytes.buffer