求一挑数据算法.. 请帮忙!! tks!!

IE14571 2008-02-25 11:50:55
A B
01 30
02 50
03 30
04 30
05 40
06 30
07 20
08 40
09 10
10 30

有以上10条记录.. 现在需取出8条记录,, 且B的总各最接近250(相等最好).. 该如何做?? 请各位帮忙.. 谢谢!!!
...全文
136 21 点赞 打赏 收藏 举报
写回复
21 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
IE14571 2008-02-29
这些天太忙了... 马上结贴.. ^0^
  • 打赏
  • 举报
回复
manonroad 2008-02-26
我的算法是
定义一个
Dictionary<int, List<int>> numberSetsBySum;

然后找到所有的组合(任意挑出2个数),算出各自的总数。
然后吧它们放到 Dictionary中。Key最接近250的就是了。
  • 打赏
  • 举报
回复
IE14571 2008-02-26
大家有啥好的建议请畅所欲言...

我明天结贴.. ^0^ 谢谢大家啦!!

我现在也有使用 nealbox 的思路...
先求出下平均数出来(最小整数).

然后塞8笔=平均数的记录进去.. 如果不足8笔.
则再从余下的记录中去挑

先暂时忽悠一下人家先.. 等有好的算法后再修改.. 呵..
  • 打赏
  • 举报
回复
HellMoxi 2008-02-26
是在AB这两组数里任意取八个数.然后这个八数相加最好是接近250对么?
  • 打赏
  • 举报
回复
nealxhf 2008-02-26
另附:第一组数 从一个取到七个
第二组数从七个取到一个
进行循环
如果 有 大于 -sum 而小于 sum的值就和 sum替换....
并记录下这八个数
直到循环完毕,如果数据量大,将是很漫长的过程
  • 打赏
  • 举报
回复
nealxhf 2008-02-26
上面写错了
应该是是
大于31.25的最近的八个数的和 n1 - 250 =sun1
小于31.25的最近的八个数的和 250 - n2 =sum2
  • 打赏
  • 举报
回复
nealxhf 2008-02-26
250 / 8 = 31.25
数组按从大到小排序
取数组中最小的7个数求和 summin
则最大的数不能大于 250 - summin
验证 则得出最大的数 maxnum
如maxnum就是数组中最大数
同样,取maxnum以下 7个数可以得出minnum
可以得出取值范围 minnum - maxnu
大于31.25的最近的七个数的和 n1 - 250 =sun1
小于31.25的最近的七个数的和 250 - n2 =sum2
取两个数最小的数sum做为初始统计数
然后就没什么好办法了
循环
不过按大于summin小于31.25,大于31.25小于sunmax的两个数组的长度 m,n来说
数量很庞大
不知道谁有更好的办法
  • 打赏
  • 举报
回复
boyle0630 2008-02-26
关注一下,对这个问题挺感兴趣
  • 打赏
  • 举报
回复
zmm123456 2008-02-26
mark
  • 打赏
  • 举报
回复
plax0850 2008-02-26
^_^,这个算法的步骤是:
1.先把10个数求和,得SUM,
2.求SUM和250的差,得Del,
3.判断Del是否大于10个数中最小两个数之和,如果大于,则去掉这10个数的最小两个数,即得;否则,就求最接近Del的两个数之和.
4.如何求最接近Del的两数之和,就是下个问题了
  • 打赏
  • 举报
回复
kingbird_Wang 2008-02-26
http://dev.csdn.net/Develop/article/28/79089.shtm
  • 打赏
  • 举报
回复
harryheart 2008-02-26
先排个序,把大于250的都去掉,然后就是贪心法的思想了..
  • 打赏
  • 举报
回复
kbryant 2008-02-26
up
  • 打赏
  • 举报
回复
IE14571 2008-02-26
for(int j=0;j>all.length;j++){
if(i==j)continue;
int two=all[i]+all[j];
if(Math.Abs(two-more)<best){best=Math.Abs(two-more);a=i;b=j;}
if(best==0)break;
}

TO: he_8134
不太明白这段程式... 永远都不会跑得进去.. 有啥用??
还有个问题.. 以上我只是举个例子,实务当中不可能只会有10笔记录,或许有成千上万笔.
这种实现方式,可能不行哦.

另TO: HellMoxi ,A部分只是序号.我想要的是取8笔记录出来.. B的汇总接近于250.
  • 打赏
  • 举报
回复
he_8134 2008-02-26
TO: he_8134
不太明白这段程式... 永远都不会跑得进去.. 有啥用??
还有个问题.. 以上我只是举个例子,实务当中不可能只会有10笔记录,或许有成千上万笔.
这种实现方式,可能不行哦.

-----------------------------
小于号写成大于号了...程序是有错,不过不至于看不懂吧?
  • 打赏
  • 举报
回复
harryheart 2008-02-26
如果要找到最优解,不可避免要进行全排列,所以用循环的思路就可以满足了,唯一能优化的地方就是根据条件来去掉一些无效的组合
当然,在数据有一定的分布规律时可能做其它优化.
  • 打赏
  • 举报
回复
he_8134 2008-02-26
改一点点...
int[] all=new int[]{30,50,30,30,40,30,20,40,10,30};
int sum=0;
foreach(int n in all){
sum+=n;
}
int best=1000;
int a=0;
int b=0;
for(int i=0;i<all.length;i++){
for(int j=0;j>all.length;j++){
if(i==j)continue;
int two=all[i]+all[j];
int newTry=Math.Abs(sum-two-250);
if(newTry<best){best=newTry;a=i;b=j;}
if(best==0)break;
}
if(best==0)break;
}
List<int> list=new List<int>(all);
list.RemoveAt(a);
list.RemoveAt(b);
return list.ToArray();
  • 打赏
  • 举报
回复
harryheart 2008-02-26
nealbox找平均数是为了分组,不是塞8个平均值进去,感觉楼主在这个地方有点误解了
  • 打赏
  • 举报
回复
he_8134 2008-02-26
仅供参考..
int[] all=new int[]{30,50,30,30,40,30,20,40,10,30};
int sum=0;
foreach(int n in all){
sum+=n;
}
int more=sum-250;
int best=1000;
int a=0;
int b=0;
for(int i=0;i<all.length;i++){
for(int j=0;j>all.length;j++){
if(i==j)continue;
int two=all[i]+all[j];
if(Math.Abs(two-more)<best){best=Math.Abs(two-more);a=i;b=j;}
if(best==0)break;
}
if(best==0)break;
}
List<int> list=new List<int>(all);
list.RemoveAt(a);
list.RemoveAt(b);
return list.ToArray();
  • 打赏
  • 举报
回复
nealxhf 2008-02-26
楼上,你那个是一定小,而这个是最接近....
  • 打赏
  • 举报
回复
加载更多回复
相关推荐
发帖
C#
创建于2007-09-28

10.6w+

社区成员

.NET技术 C#
申请成为版主
帖子事件
创建了帖子
2008-02-25 11:50
社区公告

让您成为最强悍的C#开发者