数据算法,非高手莫入

wangdetian168 2008-08-26 09:29:26
标准材料有若干根6m的木材
要取
3m的5根
1.55m的7根
1.66m的9根
等等
如何才能是用的6m的材料最少呢
这个算法思路是什么
该怎么写呢
...全文
501 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
fishidea 2008-08-27
  • 打赏
  • 举报
回复
怎么感觉有点象成本管理的方面?
呵呵,不错的题目噢~LZ用大家的方法看看吧,MS现在有很多这方面的需求嘛,有经验的不妨分享一下下:)
cat_hsfz 2008-08-27
  • 打赏
  • 举报
回复
这么小规模的问题,穷举就行啦,甚至人手穷举都可以。至于此类组合问题,通常都是NP-Hard的,除了穷举也没什么好办法能保证求到最优解,对于数据规模非常大的,通常只能考虑寻求次优解,这样才能提高效率。

以后你要算法高手,就去算法版提问,你在ASP.NET版问,等于请大家都不要回答你的问题。
nnoovvee 2008-08-27
  • 打赏
  • 举报
回复
记号
keyake863 2008-08-26
  • 打赏
  • 举报
回复
你好楼主,我实验了一个方法

这个方法得到八根,方法如下

ArrayList needs=new ArrayList();
#region 加载测试数据
for (int i = 0; i < 5; i++)
{
needs.Add(3);
}
for (int i = 0; i < 7; i++)
{
needs.Add(1.55);
}
for (int i = 0; i < 9; i++)
{
needs.Add(1.66);
}

#endregion

//从大到小排序
IComparer myComperMethod = new comper();
needs.Sort(myComperMethod);

string result = string.Empty;
//迭代方法
for (int i = 0; i < needs.Count; )
{
double temp =double.Parse(needs[i].ToString());
ArrayList tempResult = new ArrayList();
tempResult.Add(needs[i]);
needs.RemoveAt(i);

for (int j = 0; j < needs.Count; )
{
if (temp + double.Parse(needs[j].ToString()) > 6)
{
j++;
}
else
{
temp += double.Parse(needs[j].ToString());
tempResult.Add(needs[j]);

needs.RemoveAt(j);
}
}

//记录结果
for (int k= 0; k < tempResult.Count; k++)
{
result += tempResult[k].ToString() + ",";
}
result += "<br>";
}

Response.Clear();
Response.Write(result);
Response.End();


//排序方法
public class comper : IComparer
{
int IComparer.Compare(object a, object b)
{
float flotA = 0, flotB = 0;
bool isFloat = float.TryParse(a.ToString(), out flotA) && float.TryParse(b.ToString(), out flotB);
if (!isFloat)
{
return -string.Compare(a.ToString(), b.ToString(), false);
}
else
{
return flotA == flotB ? 0 : (flotA > flotB ? -1 : 1);
}
}
}


输出结果如下:
3,3,
3,3,
3,1.66,
1.66,1.66,1.66,
1.66,1.66,1.66,
1.66,1.66,1.55,
1.55,1.55,1.55,
1.55,1.55,1.55,
编程有钱人了 2008-08-26
  • 打赏
  • 举报
回复
gs
wangkun9999 2008-08-26
  • 打赏
  • 举报
回复

while (l>((Material)s[i]).Materiallen && ((Material)s[i]).MaterialCount>0)
改成
while (l>=((Material)s[i]).Materiallen && ((Material)s[i]).MaterialCount>0)


呵呵,结果变成8,从大到小和从小到大好像都一样,不过不按顺序来返回的结果不知道怎样,lz自己去测试吧.
walk121 2008-08-26
  • 打赏
  • 举报
回复
这样题目用不着高手
sxmonsy 2008-08-26
  • 打赏
  • 举报
回复
设数组N.A为剩材(A=6-N).
循环: A=6-Nn //看剩材里有没有能切的大小.在这里做个双重循环.循环n.看A还能不能继续切.然后取循环数最多的一个.
delete(Nn) //把做好的去掉
超级大笨狼 2008-08-26
  • 打赏
  • 举报
回复
贪心算法就可以算出来.
0-1规划.
基本上是蛮力算法
wangkun9999 2008-08-26
  • 打赏
  • 举报
回复
我得到的结果是9根;
我上面的算法其实可以不按顺序来取(和我先前的思路有点出入),算法方面还可以在(计算剩余成品数)这一环节上再优化下^_^
wangkun9999 2008-08-26
  • 打赏
  • 举报
回复

按上面的取大优先原则写了一个算法:

private void Page_Load(object sender, System.EventArgs e)
{
// 在此处放置用户代码以初始化页面

ArrayList s=new ArrayList();
Material myMaterial=new Material();
myMaterial.Materiallen=3.00;
myMaterial.MaterialCount=5;
s.Add(myMaterial);

myMaterial=new Material();
myMaterial.Materiallen=1.66;
myMaterial.MaterialCount=9;
s.Add(myMaterial);

myMaterial=new Material();
myMaterial.Materiallen=1.55;
myMaterial.MaterialCount=7;
s.Add(myMaterial);

//s.Sort(); //排序

Double l=6; //材料长度
int lc=0; //使用材料数
int tolc=0; //剩余成品数;
int i=0;



while (true)
{
i=0;
l=6;
tolc=0;
while(i<s.Count) //对每根材料(6m)进行一次堆分
{
while (l>((Material)s[i]).Materiallen && ((Material)s[i]).MaterialCount>0)
{
l-=((Material)s[i]).Materiallen;
((Material)s[i]).MaterialCount-=1;
}
i++;
if (i==s.Count)
{
lc++;
break;
}
}

//计算剩余成品数
for (int j=0;j<s.Count;j++) tolc+=((Material)s[j]).MaterialCount;
if (tolc==0) break;
}

Response.Write(lc);

}

public class Material
{
private Double _Materiallen;
private int _MaterialCount;
public Double Materiallen
{
set{ _Materiallen=value;}
get{return _Materiallen;}
}
public int MaterialCount
{
set{ _MaterialCount=value;}
get{return _MaterialCount;}
}
}

rczjp 2008-08-26
  • 打赏
  • 举报
回复
哦 确实应该从小取到大... 就这个题目来说是 7根 呵呵...
rczjp 2008-08-26
  • 打赏
  • 举报
回复
从大到小的取和从小到大的取 效果一样把
大的剩下的也许可以给小的,小的剩下的也给不了大的
lfywy 2008-08-26
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 wangkun9999 的回复:]
lz上次好像问过相同的问题~~
原则就是取大优先:
从3m-1.66m-1.55m顺序取值;
第一步:先取完3m的,取下的材料依次按1.66m-1.55m往下取,不能取的舍弃;
第二步:重复第一步就行了.
[/Quote]
这个是好办法,不过效率可能不高
lihongdian 2008-08-26
  • 打赏
  • 举报
回复
LZ明白我的意思没?
明白了吭声.

我的意思就是说比如我有1.11,1.22,1.33,1.44,1.55,1.66,1.77,1.88等等块木头需求.

不管需要的数目,先一个取一根.算出最优比例.

也就是六分之1.11+六分之1.22..........加出来最优.

然后根据得到的木头型号减去1根.表示你已经得到一根了.再算剩下的.

层层递归.
wangdetian168 2008-08-26
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 lihongdian 的回复:]
引用 16 楼 wangkun9999 的回复:
lz上次好像问过相同的问题~~
原则就是取大优先:
从3m-1.66m-1.55m顺序取值;
第一步:先取完3m的,取下的材料依次按1.66m-1.55m往下取,不能取的舍弃;
第二步:重复第一步就行了.


不能从大往小取.这样会浪费材料
[/Quote]
说的有理的确
shrinerain 2008-08-26
  • 打赏
  • 举报
回复
google "贪心算法" , "动态规划解决背包问题"
lihongdian 2008-08-26
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 wangkun9999 的回复:]
lz上次好像问过相同的问题~~
原则就是取大优先:
从3m-1.66m-1.55m顺序取值;
第一步:先取完3m的,取下的材料依次按1.66m-1.55m往下取,不能取的舍弃;
第二步:重复第一步就行了.
[/Quote]

不能从大往小取.这样会浪费材料
lihongdian 2008-08-26
  • 打赏
  • 举报
回复
最笨的方法:

设: n1~nX种长度的木材.每种需要nM1~nMX根.

排序n1~nX.

如果nX小于6,则计算n1+nX是否小于6.使用两头加的办法.

比如需要长度是1.44,1.55,1.66,1.77,1.88.

那么就用1.88+1.44<6,再加上1.55.还是小于6.再加1.66大于6.返回加1.55,返回加1.44.每加一次就把相应nMX的数量

减1.直到0为止.

这种办法最笨最直观.
wangkun9999 2008-08-26
  • 打赏
  • 举报
回复
lz上次好像问过相同的问题~~
原则就是取大优先:
从3m-1.66m-1.55m顺序取值;
第一步:先取完3m的,取下的材料依次按1.66m-1.55m往下取,不能取的舍弃;
第二步:重复第一步就行了.
加载更多回复(19)

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

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