求一非递归算法!非递归!

千杯不醉-sen 2012-09-21 03:29:34
在实际生活中遇到一些问题,现在简单描述一下,希望大家有什么好的算法告诉我,有源码更好。

问题描述:

前提:原材可以无限制取,但最终余材要最少。

详细描述:开始只有原材,余材为零。原材可能有多种,按照某种情况截取,第一次截取后如果余材不为0则归类为余

材,下次截取时先在余材中寻找符合条件的,有则继续在余材中寻找下一个符合条件的,反之在原材中寻找。

例1:
原材长度:3m,7m,9m(各有无限根)
余材长度:0m
截取情况:4根2m的
获得结果:取9m的1根余1m,余材1m

例2:
原材长度:3m,8m,9m
余材长度:0m
截取情况:4根2m的
获得结果:取8m的1根余0m,余材0m

例3:
原材长度:3m,7m
余材长度:0m
截取情况:4根2m的
获得结果:取3m的1根余1m,取7m的一根余1,m,余材1m,1m,总共2m

例4:
原材长度:3m,7m
余材长度:0m
截取情况:1根2m的
获得结果:取3m的1根余1m,余材1m

例5:
原材长度:3m,7m,9m
余材长度:0m
截取情况:2根3m的,4根2m的
获得结果:取3m的2根余0m,取9m的一根余1m,总共余材1m

例5:
原材长度:4m,7m,9m
余材长度:0m
截取情况:2根3m的,4根2m的
获得结果:取1根7m的余1根1m,取1根9m的余1m,总共余2m





...全文
292 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
cfvmario 2012-10-23
  • 打赏
  • 举报
回复
如果限制整数范围
肯定应该是先从拼的角度考虑 能拼出原材的最好 拼不出来的必须有废料的才进行问题分解
天涯倦客 2012-10-23
  • 打赏
  • 举报
回复
还需要一些约束的。。

搞过门窗的。。

千杯不醉-sen 2012-10-23
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 的回复:]

据说国外一个材料最优化软件就是人工配置了各种情况的取值,而不是算法。卖几百万
[/Quote]

额...
yymycabbage 2012-10-23
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 的回复:]

引用 20 楼 的回复:

据说国外一个材料最优化软件就是人工配置了各种情况的取值,而不是算法。卖几百万


额...
[/Quote]

我觉得人工配置未必不是一个办法啊,如果实际生产中用料情况有限的话,把预先的数据全部放入数据库中,无法匹配的时候使用人工输入,使用一段时间后,基本上没有找不到的case了
ouPuso 2012-09-29
  • 打赏
  • 举报
回复
各自的余料或费料什么的由原料自己维护,取料时由原料方决定是给出原料还是余料
OO_is_just_P 2012-09-29
  • 打赏
  • 举报
回复
据说国外一个材料最优化软件就是人工配置了各种情况的取值,而不是算法。卖几百万
tigerii 2012-09-29
  • 打赏
  • 举报
回复
例五,用两根7米的完成的,实际应用中,客户就倒霉了
千杯不醉-sen 2012-09-24
  • 打赏
  • 举报
回复
这是之前的算法,用的是深度搜索,实际中可能会存在一些问题,想用非递归取实现,暂时没有想到合适的优化方案。

procedure DFS(ABarIndex, ABarCount: Integer);
var
I, nUnusedLen: Integer;
begin
//剪枝
if (nHaveWasted > nMinWaste) or ((nLenCanUsed - nAllBarLen) > nMinWaste) then
Exit;
Inc(nTerminationCount);
if (ABarIndex = 0) and (ABarCount = -1) then //找到一个方案
begin
nMinWaste := nLenCanUsed; //更新找到的更小的消耗
SetLength(oBestAns, Length(oFindAns));
for I := Low(oFindAns) to High(oFindAns) do
oBestAns[I] := oFindAns[I];
oBestSurplusList := oSaveSurplusList; //记录最好方案时剩下的料头
Exit;
end;
if nTerminationCount >= 100000 then
Exit; //达到一定搜索次数就退出,避免数据量过大时死机
if (ABarIndex > 0) and (ABarCount = -1) then
begin
Dec(ABarIndex);
ABarCount := ABarList[ABarIndex].Count - 1;
DFS(ABarIndex, ABarCount);
Exit;
end;
//先从已经分配的料中里面搜索
for I := Low(oFindAns) to High(oFindAns) do
if oFindAns[I].UnUsedlen >= ABarList[ABarIndex].Len then
begin
oBarList := oFindAns[I].BarList;
SetLength(oBarList, Length(oBarList) + 1);
oBarList[High(oBarList)] := ABarList[ABarIndex];
oBarList[High(oBarList)].Count := 1;
oFindAns[I].BarList := oBarList;

nLenCanUsed := nLenCanUsed - ABarList[ABarIndex].Len;
nAllBarLen := nAllBarLen - ABarList[ABarIndex].Len;
nUnusedLen := oFindAns[I].UnUsedlen;
if nUnusedLen < nMinBarLen then
nHaveWasted := nHaveWasted + nUnusedLen; //更新已经确定消耗了的

DFS(ABarIndex, ABarCount - 1);
//恢复原样
if nUnusedLen < nMinBarLen then
nHaveWasted := nHaveWasted - nUnusedLen;
nAllBarLen := nAllBarLen + ABarList[ABarIndex].Len;
nLenCanUsed := nLenCanUsed + ABarList[ABarIndex].Len;
oBarList := oFindAns[I].BarList;
SetLength(oBarList, High(oBarList));
oFindAns[I].BarList := oBarList;
end;
//从原材里面搜索
for I := Low(oSaveSurplusList) to High(oSaveSurplusList) do
if (oSaveSurplusList[I].Count <> 0) and (oSaveSurplusList[I].Len >= ABarList[ABarIndex].Len) then
begin
Dec(oSaveSurplusList[I].Count);
SetLength(oBarList, 1);
oBarList[0] := ABarList[ABarIndex];
oBarList[0].Count := 1;
if oSaveSurplusList[I].Count >= 0 then
sRemark := SSurplus
else
sRemark := SMaterials;
SetLength(oFindAns, Length(oFindAns) + 1);
oFindAns[High(oFindAns)] := DetailsData(Length(oFindAns), 1, oSaveSurplusList[I].Len,
ABarList[ABarIndex].BarFormat, oBarList, sRemark);

nUnusedLen := oFindAns[High(oFindAns)].UnUsedlen;
nLenCanUsed := nLenCanUsed + nUnusedLen;
nAllBarLen := nAllBarLen - ABarlist[ABarIndex].Len;
if nUnusedLen < nMinBarLen then
nHaveWasted := nHaveWasted + nUnusedLen;
DFS(ABarIndex, ABarCount - 1);

//恢复数据
if nUnusedLen < nMinBarLen then
nHaveWasted := nHaveWasted - nUnusedLen;
nAllBarLen := nAllBarLen + ABarlist[ABarIndex].Len;
nLenCanUsed := nLenCanUsed - nUnusedLen;
SetLength(oFindAns, High(oFindAns));
Inc(oSaveSurplusList[I].Count);
end;
end;

谁有好的想法,帮忙优化一下,小弟在此先谢谢各位啦~
千杯不醉-sen 2012-09-24
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]

比较大小 、取模並求余、再比较大小, 如此反复
[/Quote]

这位仁兄,说明白一点,原长度和要截取的长度?这样做的道理是什么?
千杯不醉-sen 2012-09-24
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]

如果不是短暂的开料,在实际工程管理上,这类问题除了代码上的逻辑算法外,还有一个业务逻辑在里面的。比如,生产过程中,不存在1米的需求,那么,1米的余料就再不是余料,而是废料了(当然,这个1米是个举例,但不管怎样,总有一个尺寸是作为废料的值,为了好理解,就定它为1米),当这情况成立时,就要考虑开料过程中,尽量不产生余下1米的事情发生。所以,以楼主的例1来说,就不能取一条9米来开料了,而是拿2条7米开……
[/Quote]

我仔细想了一下,要是这样考虑废料的话感觉越复杂了。
kaikai_kk 2012-09-24
  • 打赏
  • 举报
回复
比较大小 、取模並求余、再比较大小, 如此反复
千杯不醉-sen 2012-09-24
  • 打赏
  • 举报
回复
我可能没说清楚,按照你的理解来就ok~
千杯不醉-sen 2012-09-24
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]

如果不是短暂的开料,在实际工程管理上,这类问题除了代码上的逻辑算法外,还有一个业务逻辑在里面的。比如,生产过程中,不存在1米的需求,那么,1米的余料就再不是余料,而是废料了(当然,这个1米是个举例,但不管怎样,总有一个尺寸是作为废料的值,为了好理解,就定它为1米),当这情况成立时,就要考虑开料过程中,尽量不产生余下1米的事情发生。所以,以楼主的例1来说,就不能取一条9米来开料了,而是拿2条7米开……
[/Quote]

这位大哥说的在理,其实我想问的就是开料问题,废料是值得考虑的东西,业务知识太庞大,没注意到这一点。可以看得出你知道这方面的知识,还请不吝赐教,谢谢~
haitao 2012-09-22
  • 打赏
  • 举报
回复
一种是循环2^n次,每次就是一种组合,取出它的每一位,0还是1就代表。。。。

一种是回溯法
死循环:
设好递进条件和动作
设好没法递进后的回退机制
设好得到答案或全部完成的判断条件
广州佬 2012-09-22
  • 打赏
  • 举报
回复
如果不是短暂的开料,在实际工程管理上,这类问题除了代码上的逻辑算法外,还有一个业务逻辑在里面的。比如,生产过程中,不存在1米的需求,那么,1米的余料就再不是余料,而是废料了(当然,这个1米是个举例,但不管怎样,总有一个尺寸是作为废料的值,为了好理解,就定它为1米),当这情况成立时,就要考虑开料过程中,尽量不产生余下1米的事情发生。所以,以楼主的例1来说,就不能取一条9米来开料了,而是拿2条7米开,余两条3米留给下一规格使用。即使如此,还要看具体情况,假如3米的需求不多,那么余下一大堆3米的料堆在一边,仍然是浪费。因此,除了楼上各位大哥的高见外,还要进行一些耗料统计,以符合一个合理的业务逻辑需求。
如果各种尺寸的需求是均匀的话,一般来说,用料遵循的原则:优先无余;用余从短。不均匀的,那就只能按楼主例1的方式进行了。
千杯不醉-sen 2012-09-21
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

完全遍历、枚举?
自动尝试所有排列、组合的每一种情况
[/Quote]

理论上是这样,请问非递归该如何实现?
千杯不醉-sen 2012-09-21
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

我觉得 这算法就是先拼成 原材的长度 这样会最省.


所以从截取情况里面 调试出来 怎么能拼成原材长度
[/Quote]

想法是好的,原材长度有多种,如何处理?
千杯不醉-sen 2012-09-21
  • 打赏
  • 举报
回复
那些例子是我随便写的,考虑不周的地方还请谅解。大体就是那个意思,求全局最优。

全排列不用递归杂么写?递归的以前倒是写过,还请指点一下~~~
爱蹄子的羊头 2012-09-21
  • 打赏
  • 举报
回复
我觉得 这算法就是先拼成 原材的长度 这样会最省.


所以从截取情况里面 调试出来 怎么能拼成原材长度
千杯不醉-sen 2012-09-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

有点意思,先Mark一下,
引用楼主 的回复:
例5:
原材长度:4m,7m,9m
余材长度:0m
截取情况:2根3m的,4根2m的
获得结果:取1根7m的余1根1m,取1根9m的余1m,总共余2m

这个的最优为啥不是2个7m(=2+2+3)的,最后余0呢?
[/Quote]
例5:
原材长度:3m,7m,9m
余材长度:0m
截取情况:2根3m的,4根2m的
获得结果:取3m的2根余0m,取9m的一根余1m,总共余材1m

例6:
原材长度:4m,7m,9m
余材长度:0m
截取情况:2根3m的,4根2m的
获得结果:取1根7m的余1根1m,取1根9m的余1m,总共余2m
确实,这两个举例是错误的。

例5:
原材长度:3m,7m,9m
余材长度:0m
截取情况:2根3m的,4根2m的
获得结果:取7m的2根余0m
加载更多回复(4)

16,749

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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