石材切割1------简单递归

石材切割1------简单递归

问题描述

给定一个最大的总切割目标石块,再给定一系列我们需要的样板石块。寻找切割方法使得我们从目标石块上切割出的所需样板石块的面积和最大,即对目标石块的利用率最高。限制切割为一刀切,即一次切割必须把一块石板一分为二,不能只切一段。

在这里插入图片描述

算法设计

将所需的样板模块按照面积从大到小进行排序,每次取最大并且可以切割的那块进行切割,在数据量非常大的情况下,单步的最优利用率可能导致全局的最优利用率。首先读入数据,将待切割的石块存入details中。进行递归切割,如果待切割的石块和样板的长度相等,则从宽度上切割,如果宽度相等,则从长度上进行切割。如果长度,宽度都小于,则优先从宽度上切割。

python代码实现
main_sheet = {  
    'l': 0,  
    'w': 0, 
    's': 0
}
main_sheet_square = 0  # 总面积
details = list() 
details_square = 0  #小石块面积

#判空
def isempty():
    for i in details:
        if i['flag'] == 0:
            return False
    return True

#获取信息
def get_details():
    f = open('nice1.txt', 'r')
    global details_square, main_sheet_square, details
    l = f.readline().split()
    main_sheet['l'] = (int)(input("输入石板的长:"))
    main_sheet['w'] = (int)(input("输入石板的宽:"))
    main_sheet_square = main_sheet['l'] * main_sheet['w']  
    for line in f:
        s = line.split()
        detail_length = int(s[0])
        detail_width = int(s[1])
        detail_square = detail_length*detail_width
        if detail_length < detail_width:  #保证长比宽大
            detail_length, detail_width = detail_width, detail_length
        details.append({
            'l': detail_length,
            'w': detail_width,
            's':detail_square,
            'flag':0
        })
        details_square +=  detail_length * detail_width
    details = sorted(details, key=lambda item: (-item['l']*item['w'], -item['l']))  #按面积大小排序

def TooSmall(l,w):
    for i in details:
        if (i['l']<=l and i['w']<=w and i['flag']==0):
            return False
    return True
def cut(l,w):
    if(isempty()==True):
        return True
    if(TooSmall(l,w)==True):
        return False
    for i in range(len(details)):
        if details[i]['flag']!=1 and details[i]['l']<=l and details[i]['w']<=w:
            break
    if(details[i]['l']==l):
        details[i]['flag'] = 1
        cut(l,w-details[i]['w'])
    elif(details[i]['w']==w):
        details[i]['flag'] = 1
        cut(l-details[i]['l'],w)
    elif(details[i]['w']< w and details[i]['l']<l):
        cut(l,details[i]['w'])
        cut(l,w-details[i]['w'])

area = 0
def display():
    global area
    for item in details:
        if(item['flag']==1):
            print(item['l'],"*",item['w'])
            print(item['s'])
            area += item['s']
        else:
            print("no")

            

        
get_details() 
# print(details)
#isempty()
cut(main_sheet['l'],main_sheet['w'])
print(details)
display()
print("利用率",area/main_sheet_square)

nice1数据

549 154
319 254
170 433
166 433
226 313
133 433
124 433
195 254
179 274
151 301
135 313
228 158
206 158
122 254
179 159
273 99
92 254
77 301
273 83
273 72
115 158
228 72
90 172
228 60
90 140

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0V3jGGck-1583503162811)(C:\Users\HUAWEI\AppData\Roaming\Typora\typora-user-images\image-20200306215735336.png)]

不足

得到的实验结果其实不是最优解,也没有记录切割方法,效率较低,将在后续寻找更好的解法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值