已知钢材的总长,订单数和各订单需要的长度编制程序从订单中选择一组订单对钢材作切割加工, 使得钢材得到最佳应用,约定,每次切割损耗固定长度的钢材。
下面写一下我的思路,刚开始没有想明白应该怎么使用递归去做,但是,看了他们的代码之后,走了一遍,才明白,其实思路不太好想,但是实现起来还是比较容易的。
假设,我们有一段钢材,长度为12米,其中有3个订单,分别需要的长度为5,6,9米,每次切割总会有2米的损耗,求得其最佳订单组合。
现在我们想想一下我们正常的思路:
如果是只有一个订单的话,9米的订单是最合适的,加上2米的耗材,一共11米。
如果有两个订单的话,有组合5,6;5,9;6,9这三个组合,很明显,这三个组合都已经超过了12米的长度,因为如果是5,6的话,虽然说订单的和为11,但是有两次切割,还会有4米的耗材,加起来就是15米,已经远远超过钢材的长度了
由上面的可以知道,3个订单的组合那就更不行了。
那我们应该如何做到实现这个思路呢,我们有一个数组记录订单是否选中,请看下面这张图:
![这里写图片描述](https://box.kancloud.cn/2016-05-24_5743c075353aa.jpg "")
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;
}
}
}
}
~~~
- 前言
- 实例一:HelloWorld
- scanf函数学习
- 实数比较
- sizeof()保留字获取类型的大小
- 自增/自减学习
- C学习if条件判断和for循环
- C实现的九九乘法表
- C实现一个比较简单的猜数游戏
- 使用C模拟ATM练习switch..case用法
- 记录一个班级的成绩练习一维数组
- C数组实现矩阵的转置
- C二维数组练习
- 利用数组求前n个质数
- C实现万年历
- C实现数组中元素的排序
- C实现任意进制数的转化
- C判断一个正整数n的d进制数是否是回文数
- C使用递归实现前N个元素的和
- 钢材切割问题
- 使用指针比较整型数据的大小
- 指向数组的指针
- 寻找指定元素
- 寻找相同元素的指针
- 整数转换成罗马数字
- 字符替换
- 从键盘读入实数
- C实现字符行排版
- C实现字符排列
- C实例--判断一个字符串是否是回文数
- 通讯录的输入输出
- 扑克牌的结构定义
- 使用“结构”统计学生成绩
- 报数游戏
- 模拟社会关系
- 统计文件中字符个数
- C实现两个文件的内容输出到同一个屏幕