钢材切割问题

简介: 版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/45573057 已知钢材的总长,订单数和各订单需要的长度编制程序从订单中选择一组订单对钢材作切割加工, 使得钢材得到最佳应用,约定,每次切割损耗固定长度的钢材。
版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/45573057

已知钢材的总长,订单数和各订单需要的长度编制程序从订单中选择一组订单对钢材作切割加工, 使得钢材得到最佳应用,约定,每次切割损耗固定长度的钢材。

下面写一下我的思路,刚开始没有想明白应该怎么使用递归去做,但是,看了他们的代码之后,走了一遍,才明白,其实思路不太好想,但是实现起来还是比较容易的。

假设,我们有一段钢材,长度为12米,其中有3个订单,分别需要的长度为5,6,9米,每次切割总会有2米的损耗,求得其最佳订单组合。

现在我们想想一下我们正常的思路:
如果是只有一个订单的话,9米的订单是最合适的,加上2米的耗材,一共11米。

如果有两个订单的话,有组合5,6;5,9;6,9这三个组合,很明显,这三个组合都已经超过了12米的长度,因为如果是5,6的话,虽然说订单的和为11,但是有两次切割,还会有4米的耗材,加起来就是15米,已经远远超过钢材的长度了

由上面的可以知道,3个订单的组合那就更不行了。

那我们应该如何做到实现这个思路呢,我们有一个数组记录订单是否选中,请看下面这张图:

这里写图片描述

5,6,9初始化的时候,全是未选中的状态,程序开始执行,先选中5,加上损耗的长度小于12,则继续选中6,这样加上损耗的长度大于12了,则设置6的状态为未选中;接着选中9,5加上9加上损耗的长度,很明显超过12了,那么设置9的状态为未选中;接着从5开始的遍历完成了,将5的状态设置为未选中;选中6,再从5开始选中,这样进行下去。。。。

当然,中间需要有两个变量记录最佳长度和最佳订单组合。

下面附上我的代码:

#include <stdio.h>

/**
 * 已知钢材的总长,订单数和各订单需要的长度
 * 编制程序从订单中选择一组订单对钢材作切割加工,
 * 使得钢材得到最佳应用,约定,每次切割损耗
 * 固定长度的钢材
 */

#define N 20
#define DELTA 2 //切割钢材损耗

/** 最好的长度 **/
int bestlen;

/** 最好长度的选定订单 **/
int bestsele[N];

/** 选定订单,用于尝试选择 **/
int sele[N];

/** 有n的订单 **/
int n;

/** 订单需要的钢材的长度 **/
int orderlen[N];

/** 钢材总长度 **/
int total;

void attempt();

int main(void)
{
    int j;

    //获取钢材的总长度
    printf("Please enter the length of the steel:\n");
    scanf("%d",&total);

    //获取钢材的订单数
    printf("Please enter the number of the orders:\n");
    scanf("%d",&n);

    //获取各个订单数需要的长度
    printf("Please enter the length of every order:\n");
    for(j = 0;j < n;j++)
        scanf("%d",&orderlen[j]);

    //初始化工作,使所有的订单都没有被选中
    for(j = 0;j < n;j++)
        bestsele[j] = sele[j] = 0;

    //初始化最佳长度,设置为0
    bestlen = 0;

    //获取最佳长度
    attempt();

    printf("order:\n");
    for(j = 0;j < n;j++){
        if(bestsele[j])
            printf("%d\t",orderlen[j]);
    }
    printf("\nlength:\n%d",bestlen);

    return 0;
}

void attempt(){
    int i,len;

    //获取选中的订单的总长度(加上损耗)
    for(len = i = 0;i < n;i++)
        if(sele[i])
            len += (orderlen[i]+DELTA);

    if(len-DELTA <= total){  //注意,最后一个订单可能不需要损耗
        if(bestlen < len){
            bestlen = len;

            for(i = 0;i < n;i++)
                bestsele[i] = sele[i];
        }

        //每次尝试选择订单之后,需要将其还原未选中状态
        for(i = 0;i < n;i++){
            if(!sele[i]){
                sele[i] = 1;
                attempt();
                sele[i] = 0;
            }

        }
    }
}
目录
相关文章
|
4月前
|
计算机视觉
两种切割裁剪,切割图片的方法
两种切割裁剪,切割图片的方法
|
8月前
【每日一题Day240】LC2481分割圆的最少切割次数 | fenlei
【每日一题Day240】LC2481分割圆的最少切割次数 | fenlei
39 0
BNUOJ 44584 平面切割者
BNUOJ 44584 平面切割者
108 0
|
Perl
日志切割操作
Linux日志切割操作,取出需要的日志内容
294 0
|
应用服务中间件
使用logrotate切割日志
假设要进行日志切割的目录为:/home/test/tomcat-test/logs/catalina.out 首先进到这个目录下:/etc/logrotate.d/ #cd /etc/logrotate.
1242 0
|
算法 C#
任意多边形切割/裁剪(附C#代码实现)
原文:任意多边形切割/裁剪(附C#代码实现) 本实现主要参考了发表于2003年《软件学报》的《一个有效的多边形裁剪算法》(刘勇奎,高云,黄有群)这篇论文,所使用的理论与算法大都基于本文,对论文中部分阐述进行了详细解释,并提取了论文中一些重要的理论加以汇总。
1836 0
|
监控 应用服务中间件 nginx
日志切割之Logrotate
1、关于日志切割   日志文件包含了关于系统中发生的事件的有用信息,在排障过程中或者系统性能分析时经常被用到。对于忙碌的服务器,日志文件大小会增长极快,服务器会很快消耗磁盘空间,这成了个问题。除此之外,处理一个单个的庞大日志文件也常常是件十分棘手的事。
1710 0
|
前端开发 JavaScript 开发工具
|
开发框架 JavaScript 前端开发