一个集合,划分成2个子集,使子集满足特定条件

smartcatiboy 2009-06-14 12:34:57
假设存在一个N个数的集合TotalSet(a1,a2,a3....aN),其中N>100 ,(其中aN不是有规律的数)
求一算法
使TotalSet划分为两个子集合subSet1和subSet2,
其中subSet1 U subSet2 = TotalSet,subSet1中所有元素的和subSet2的所有元素和相差最小
要求全部解。

例如
{1,3,7,8,0} 可以划分成 {1,8}{3,7,0} 或者{1,8,0}{3,7}


(由于N>100,所以无法求powerset然后比较)

大家有办法吗?

参考:
http://topic.csdn.net/u/20090612/04/0857e3ca-b19f-43c0-abe3-b5fc7914f6d9.html?33672
...全文
657 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
hecker728 2009-06-15
  • 打赏
  • 举报
回复
学习下
smartcatiboy 2009-06-15
  • 打赏
  • 举报
回复
感谢回复
tanwan 2009-06-14
  • 打赏
  • 举报
回复
min(|dp[1,i]-dp[i+1,j]|)这样应该可以...
zhangbiao1981 2009-06-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 litaoye 的回复:]
其实思路是差不多的,并且求subset1的和就可以,subset2的和的可能 等价于 subset1的和的可能

用动态规划解01背包(不是用那种二进制的方法),其实也是这个思路,复杂度并不是2^n,而是sum*n
其中有许多的解都是重复的,用动态规划的方法就可以将2^n个状态压缩为不超过sum个状态。

引用 4 楼 zhangbiao1981 的回复:
引用 3 楼 litaoye 的回复:
这题讨论好多次了,其实就是一个sum/2的01背包问题,并且物品的体积等于物品…
[/Quote]
赞分析!
绿色夹克衫 2009-06-14
  • 打赏
  • 举报
回复
其实思路是差不多的,并且求subset1的和就可以,subset2的和的可能 等价于 subset1的和的可能

用动态规划解01背包(不是用那种二进制的方法),其实也是这个思路,复杂度并不是2^n,而是sum*n
其中有许多的解都是重复的,用动态规划的方法就可以将2^n个状态压缩为不超过sum个状态。

[Quote=引用 4 楼 zhangbiao1981 的回复:]
引用 3 楼 litaoye 的回复:
这题讨论好多次了,其实就是一个sum/2的01背包问题,并且物品的体积等于物品的价值。

C# codeclassProgram1005
{//用来记录已经计算过的中间状态,类似于dppublicstaticDictionary <ulong,int>hash;//物品的重量publicstaticint[] weight;//做个累加为了能够更大幅度的作剪枝publicstaticint[] accumulate;staticvoidsolve()
{//处理输入的部分intN=int.Parse(Console.ReadLine()…
[/Quote]
zhangbiao1981 2009-06-14
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 litaoye 的回复:]
这题讨论好多次了,其实就是一个sum/2的01背包问题,并且物品的体积等于物品的价值。

C# codeclassProgram1005
{//用来记录已经计算过的中间状态,类似于dppublicstaticDictionary<ulong,int>hash;//物品的重量publicstaticint[] weight;//做个累加为了能够更大幅度的作剪枝publicstaticint[] accumulate;staticvoidsolve()
{//处理输入的部分intN=int.Parse(Console.ReadLine());string[] inputArray=Console.Rea…
[/Quote]
感觉把它看成背包问题有点复杂,我上面得那种思路仅用一个set做数据结构,比背包问题要清晰些,不知道牛人怎么看?
绿色夹克衫 2009-06-14
  • 打赏
  • 举报
回复
这题讨论好多次了,其实就是一个sum/2的01背包问题,并且物品的体积等于物品的价值。


class Program1005
{
//用来记录已经计算过的中间状态,类似于dp
public static Dictionary<ulong, int> hash;

//物品的重量
public static int[] weight;

//做个累加为了能够更大幅度的作剪枝
public static int[] accumulate;

static void solve()
{
//处理输入的部分
int N = int.Parse(Console.ReadLine());
string[] inputArray = Console.ReadLine().Split(' ');

weight = new int[N];
accumulate = new int[N];
hash = new Dictionary<ulong, int>();

for (int i = 0; i < N; i++)
weight[i] = int.Parse(inputArray[i]);

//排个序,方便剪枝
Array.Sort(weight);
int sum = 0;

//计算累加
for (int i = N - 1; i >= 0; i--)
{
sum += weight[i];
accumulate[i] = sum;
}

//背包大小为sum / 2,sum >> 1 = sum / 2
int max = backpack(sum >> 1, 0);
Console.WriteLine(sum - (max << 1));
}

//背包程序部分
static int backpack(int size, int position)
{
if (position >= weight.Length)
return 0;

if (size == weight[position] || size == accumulate[position])
return size;

if (size < weight[position])
return backpack(size, position + 1);

if(size > accumulate[position])
return backpack(size - weight[position], position + 1) + weight[position];

ulong hashCode = (ulong)(position * 10000000 + size);

if (hash.ContainsKey(hashCode))
return hash[hashCode];

int NoMax = backpack(size, position + 1);

if (NoMax == size)
{
hash.Add(hashCode, NoMax);
return NoMax;
}

int YesMax = backpack(size - weight[position], position + 1) + weight[position];

int max = Math.Max(NoMax, YesMax);
hash.Add(hashCode, max);
return max;
}
}



LZ参考一下这几个帖子吧!

http://topic.csdn.net/u/20090511/23/a482be66-6598-46fa-be19-e7e356e2244b.html

http://topic.csdn.net/u/20090601/13/672c2f5b-8e08-499c-b0b3-305e2b653bb2.html

zhangbiao1981 2009-06-14
  • 打赏
  • 举报
回复
写点伪代码:

set s = {0};
for i in (1, N){
foreach e in s{
tmp = e + TotalSet[i];
if( tmp not in s)
insert( tmp, s);
}
}

min = 正无穷大;

foreach ( e in s){ //每个e是subset1的一种可能和
sub2 = sum -e ;
diff = abs(sub2 - e);
if ( min > diff)
min = diff;
}
//min就是要求的最小差值了

zhangbiao1981 2009-06-14
  • 打赏
  • 举报
回复
感觉这个问题是一个动态规划题,如果要列出所有子集再比较,时间复杂度是幂级的。因为是求和,所有可以保留求出的和来重复利用,由于subset1的和已知的情况下,subset2的和可以通过所有数的和减去subset1的和算出来,所以只计算subset1可能形成的和就可以了,这样可以避免幂级增长。最后根据subset1所有可能的和来计算出subset2对应的所有可能和,从中找出差值最小的那对就可以了。

33,010

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧