钢材切割问题

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

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

假设,我们有一段钢材,长度为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;
            }

        }
    }
}
时间: 2024-10-12 21:47:36

钢材切割问题的相关文章

硬齿面减速机和软齿面减速机的区别

硬齿面减速机和软齿面减速机是非常热门的两款减速机.但是他们之间究竟有什么区别呢,在使用上应该如何选择呢?下面给大家讲解一下. 1.硬齿面减速机: 材料:低碳合金钢,如20CrMnTi,20CrMnMo,20CrNi2Mo,17Cr2Ni2Mo,17MnCr5. 热处理:渗碳淬火. 齿面硬度:HRC58-62. 精加工工艺:磨齿. 齿轮精度:6级. 2.软齿面减速机: 材料:45或铸钢. 热处理:调质. 齿面硬度:HB230-260(轴齿轮),HB190-220(大齿轮). 精加工工艺:精滚. 齿

机器人的逻辑

题目描述 2035年,智能机器人在各行各业中的应用已经十分普遍了,毕竟它做事时的精度与力量比一个普通人是强多了. 王涛的运输队里就有一个,是用来装卸货物的. 这天,他们的任务是要把 N(2 <= N <= 50 )根废旧的条形钢材运送到钢铁厂重新冶炼.这些钢材长短不同(有些还特别的长),为了便于运输,只好把它们切割成小段.所以,他给机器人的任务是:把这些钢材切割并装上卡车. 等机器人做完这事的时候,王涛一看结果,自己都被逗笑了:机器人的逻辑就是和人不同啊--装在车上的所有小段的钢材,居然长度都

《算法导论》中动态规划求解钢条切割问题

动态规划算法概述 动态规划(dynamic programming)1是一种与分治方法很像的方法,都是通过组合子问题的解来求解原问题.不同之处在于,动态规划用于子问题重叠的情况,比如我们学过的斐波那契数列.在斐波那契数列的求解问题中,我们经常要对一个公共子问题进行多次求解,而动态规划算法,则对每个子问题只求解一次,将其解保存在一个表格中,从而避免了大量的冗余计算量. 动态规划算法常用于寻找最优解问题(optimization problem).而其规划大概可分为四步: 1.刻画一个最优解的结构特

算法13---动态规划钢材裁剪

算法13---动态规划钢材裁剪 动态规划方法通常用来求解最优化问题.动态规划算法设计步骤: 1.刻画一个最优解的结构特征. 2.递归定义最优解的值. 3.计算最优解的值,通常采用自底向上的方法. 4.利用计算出的信息构造一个最优解. 文中给出了算法的伪代码,下面我们把递归,从顶到底,从底到顶的方法都实现一下 具体的代码如下所示 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 5 6 7 #define infinity -1 //负无穷

mysql_slow_log快速切割脚本

最近会比较多的分析mysql的慢日志,应为在mysql的慢日志中没有使用logrotate所以每次要要查看某一天到现在的慢查询日志都要使用正则工具切割,但是每次重新写就有一点麻烦,所以就用脚本写了下输入时间参数就可以切割日志的简易工具,脚本如下: #!/bin/bash #slow_log_cutting.sh version1.0 chmod 700 #use fast cutting mysql_slow_log #writer jim #history #2016.12.05 #慢日志文件

LNMP - Nginx日志切割

随着访问量的增大,如果对日志置之不理,总有一天日志文件会撑爆磁盘:所以需要我们对日志进行切割,并且每隔一段时间删除一些旧日志,防止日志无休无止的占用磁盘的空间. 可以通过写一个shell脚本自动化切割,比如每天凌晨00:00把昨天的日志进行归类重命名: # cd /usr/local/sbin # vim nginx_logrotate.sh 写入以下脚本: #! /bin/bash d=`date -d "-1 day" +%F` [ -d /tmp/nginx_log ] || m

Apache配置域名跳转、日志切割、静态缓存、防盗链、访问控制

·/usr/local/apache2/bin/apachectl  -M:查看安装了哪些模块 ·/usr/local/apache/bin/apachectl   -V:查看使用的模式 ·/usr/local/apache2/bin/apachectl  -t:检查语法错误 ·/usr/local/apache2/bin/apachectl  -l:查看安装的库文件 ·/usr/local/apache2/bin/apachectl graceful:重新加载配置 ·/usr/local/ap

2.0-apache日志切割

apache在提供服务后,在/usr/local/apache2/logs下会默认产生访问日志和错误日志access_log和error_log 尤其是访问日志,在用户访问多的情况下,会产生很多条记录.随着时间增长,可能会变成几个G或十几个G. 为了缓解这种情况,按天来切割日志,删除以前没用的日志,就成了很好的解决方法. 首先来看系统默认产生的访问日志格式: vim /usr/local/apache2/conf/httpd.conf <IfModule log_config_module>

Nginx日志切割并计划任务自动上传到FTP服务器

枫城浪子原创,转载请标明出处! 微信bh19890922 QQ445718526,490425557 更多技术博文请见个人博客: https://fengchenglangzi.000webhostapp.com http://fengchenglangzi.blog.51cto.com 一.简述 Nginx WEB服务器每天会产生大量的访问日志,而且不会自动地进行切割,如果持续天数访问,将会导致该access.log日志文件容量非常大,不便于SA查看相关的网站异常日志,并且后期进行分割非常不易