解决问题给300分

superzwb 2004-12-25 10:07:19
某种规格木材有7m,8m,9m,10m,12m五种,先需要做3m长的木材5根,怎样使用材料才能是最节省???
请教高手算法如何写?
(请注意算法和需要做木材的根数是有关系的,做5根,最佳方案一个9M和一个7M;而做6根最佳方案是2个9m)
...全文
633 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
killer1984 2005-01-07
  • 打赏
  • 举报
回复
pzcai(泡菜)的分析已经很接近正解了,在确定只取3m木材时,8m、10m用上以后都不会最省(可以用8m的地方都可以用7m,可以用10m的地方都可以用9m)。
所以问题分为两种情况:
1、只取一根,毫无疑问用7m一根
2、取一根以上,用7m(可取出2根),9m(可取出3根),12m(可取出4根)来进行组合实现。

于是将问题建模为目标规划问题(只针对第二种情况):
当要取3m木材a根时,设取7m的x根,9m的y根,12m的z根。
则问题绝对约束为2x+3y+4z >= a
目标约束为:7x+9y+12z-3a尽量趋近于0

建立方程如下(d+、d-均为一变量):
min{P2(d+ + d-)}
2x+3y+4z >= a
7x+9y+12z-3a+ d- - d+ =0
x>=0,y>=0,z>=0,d+>=0,d->=0

呵呵,看得出来,是很简单的规划题哈,解法当然就是用单纯形法进行迭代了,很多相关书籍都有介绍,大家可以找来看看,这里就不再详细写了哈。用代码也非常好实现(就是比较繁琐),已经有很多软件都做出来了。
dongpy 2005-01-07
  • 打赏
  • 举报
回复
把之前的程序改进了一下,并且仔细测试过:

//做X米长的木材N根
#include "stdio.h"
#define LEN 5
const int A[LEN]={7,8,9,10,12};
int K[LEN],tmpnum,minnum;
int Fun(int N,int B[],int L)
{
int i,j,temp,ret=0;
if (B[L-1]==0) return 0;
if(N%B[L-1]==0)
i=N/B[L-1];
else
i=N/B[L-1]+1;
if(L==1)
{
tmpnum+=i*A[L-1];
if(minnum>tmpnum||minnum==-1)
{
minnum=tmpnum;
K[L-1]=i;
return 1;
}
return 0;
}
for(j=i;j>=0;j--)
{
temp=tmpnum;
tmpnum+=j*A[L-1];
if(N<=j*B[L-1])
{
if(minnum>tmpnum||minnum==-1)
{
minnum=tmpnum;
K[L-1]=j;
ret=1;
}
}
else if(Fun(N-j*B[L-1],B,L-1))
{
K[L-1]=j;
ret=1;
}
tmpnum=temp;
}
return ret;
}

void main()
{
int B[LEN],X,N,i;
tmpnum=0;
minnum=-1;
printf("要做X米长的木材N根。\n\n输入X(长度):");
scanf("%d",&X);
printf("输入N(根数):");
scanf("%d",&N);
for(i=0;i<LEN;i++)
{
B[i]=A[i]/X;
K[i]=0;
}
if(!Fun(N,B,LEN))
printf("无法满足要求!!!\n");
else
{
printf("最佳方案为:\n");
for(i=0;i<LEN;i++)
printf("%d根%d米\n", K[i], A[i]);
}
}
idau7 2005-01-07
  • 打赏
  • 举报
回复
我找到组织了...

有点儿意思,我是来看看的..
playmud 2005-01-05
  • 打赏
  • 举报
回复
浪费的最少就是最优吧.
xuelong_zl 2005-01-04
  • 打赏
  • 举报
回复
mark
carylin 2005-01-03
  • 打赏
  • 举报
回复
也可以这样:
对7m,8m,9m,10m,12m 这5个数据取组合,可以重复。从1开始,即:
1)5中取1,对所有的组合进行判断,能够满足条件,就从能满足条件的集合中选一个最短(最优)的,此即为结果;
2)若不行,就5中取2,……
……
依次类推
Roaming_Sheep 2005-01-03
  • 打赏
  • 举报
回复
汗,8m的那根似乎永远都用不到的样子?
intellifox 2005-01-03
  • 打赏
  • 举报
回复
这个问题不好回答。
我以前做过在不定区域上铺磁砖的项目,与其属同类问题,实作时非常复杂。
这个正常用分情况来解决,楼主还可以把问题说详细点。
nwpulipeng 2005-01-02
  • 打赏
  • 举报
回复
好难!!
dongpy 2004-12-29
  • 打赏
  • 举报
回复
顺便问一下,如果做3m长的木材12根,可以3个12m、4个9m,哪一个是最佳方案呢?
好像2个都是最佳的!

楼主应该对“最佳”作个定义。
dongpy 2004-12-29
  • 打赏
  • 举报
回复
#include "stdio.h"
#define LEN 5
const int A[LEN]={7,8,9,10,12};
int K[LEN],tmpnum,minnum;
int Fun(int amount,int Arr[],int n)
{
int i,j,temp,ret=0;
i=amount/Arr[n-1];
if(n==1)
{
if(amount%Arr[n-1]==0)
j=i;
else
j=i+1;
tmpnum+=j*A[n-1];
if(minnum>tmpnum||minnum==-1)
{
minnum=tmpnum;
K[n-1]=j;
return 1;
}
return 0;
}
for(j=i;j>=0;j--)
{
temp=tmpnum;
tmpnum+=j*A[n-1];
if(Fun(amount-j*Arr[n-1],Arr,n-1))
{
K[n-1]=j;
ret=1;
}
tmpnum=temp;
}
return ret;
}

void main()
{
int B[LEN],X,N,i;
tmpnum=0;
minnum=-1;
printf("输入X(长度):");
scanf("%d",&X);
printf("输入N(根数):");
scanf("%d",&N);
for(i=0;i<LEN;i++)
{
B[i]=A[i]/X;
K[i]=0;
}
Fun(N,B,LEN);
printf("最佳方案:");
for(i=0;i<LEN;i++)
{
printf("K[%d]=%d ",i,K[i]);
}
}
输出为最佳方案的根数。 数组A需要升序排列。
zoohoo 2004-12-29
  • 打赏
  • 举报
回复
写了一个程序,用枚举的办法,在redhat7.2和solaris8上使用g++编译通过

#include <iostream>
#include <vector>

using namespace std;

const int intRaw[] = {7, 8, 9, 10, 12, 0};

class CResult
{
public:
void SetValue(int i, int j, int k, int l, int m) {
this->m_i = i;
this->m_j = j;
this->m_k = k;
this->m_l = l;
this->m_m = m;
}

Print(void) {
cout << this->m_i << " * " << intRaw[0] << " / "
<< this->m_j << " * " << intRaw[1] << " / "
<< this->m_k << " * " << intRaw[2] << " / "
<< this->m_l << " * " << intRaw[3] << " / "
<< this->m_m << " * " << intRaw[4] << endl;
}

public:
int m_i;
int m_j;
int m_k;
int m_l;
int m_m;
};

class CTest
{
public:
CTest(int length, int number): m_length(length), m_number(number) {
this->InitVec();
}

void Calc(void) {
int rest = -1, temp;
for(int i = 0; i <= this->m_number; ++ i)
for(int j = 0; j <= this->m_number; ++ j)
for(int k = 0; k <= this->m_number; ++ k)
for(int l = 0; l <= this->m_number; ++ l)
for(int m = 0; m <= this->m_number; ++ m) {
if(i * this->m_divideVec[0]
+ j * this->m_divideVec[1]
+ k * this->m_divideVec[2]
+ l * this->m_divideVec[3]
+ m * this->m_divideVec[4] == this->m_number) {
temp = i * this->m_modeVec[0]
+ j * this->m_modeVec[1]
+ k * this->m_modeVec[2]
+ l * this->m_modeVec[3]
+ m * this->m_modeVec[4];
if(rest == -1 || rest > temp) {
rest = temp;
this->m_result.SetValue(i, j, k, l, m);
}
}
}
}

void Print(void) {
this->m_result.Print();
}

private:
void InitVec(void) {
this->m_rawVec.clear();
this->m_divideVec.clear();
this->m_modeVec.clear();

int i = 0;
while(intRaw[i] != 0) {
this->m_rawVec.push_back(intRaw[i]);
this->m_divideVec.push_back(intRaw[i] / this->m_length);
this->m_modeVec.push_back(intRaw[i] % this->m_length);
++ i;
}
}

private:
int m_length;
int m_number;
CResult m_result;

vector<int> m_rawVec;
vector<int> m_divideVec;
vector<int> m_modeVec;
}; // class CTest


int main(int argc, char *argv[])
{
CTest test(3, 5);
test.Calc();
test.Print();
return 0;
}

输出为:1 * 7 / 0 * 8 / 1 * 9 / 0 * 10 / 0 * 12
使用7m和9m的木头各一根,即为最省的方法
dongpy 2004-12-29
  • 打赏
  • 举报
回复
假设需要做X米长的木材N根。
已知木材规格7、8、9、10、12,设为数组int A[5].
每种规格木材(1根)能做的根数 设为int B[5],B[i]=A[i]/X,i=0,..4
令N=K0*B[0]+...+K4*B[4] (Ki>=0,i=0,..4)
则原料总数M=K0*A[0]+...+K4*A[4]
M最小时的Ki(i=0,..4)即为最佳方案。
test22004 2004-12-27
  • 打赏
  • 举报
回复

第一步是为了不让总和超过3 也就是第一步过滤
test22004 2004-12-27
  • 打赏
  • 举报
回复
注意是得出的确原料摸3

然后求摸的和最小的
test22004 2004-12-27
  • 打赏
  • 举报
回复
需求总数-原料1+原料2

得数摸3 求摸最小的
260005065 2004-12-25
  • 打赏
  • 举报
回复
这是数学问题吧,没什么算法啊?
需要做3m长的木材1根 一个7
需要做3m长的木材2根 一个7
需要做3m长的木材3根 一个9
需要做3m长的木材4根 一个12
需要做3m长的木材5根 一个7、一个9
需要做3m长的木材6根 两个9
需要做3m长的木材7根 一个9、一个12

设需要做3m长的木材 x 根 (x > 8)
有 x = 4*m + k ==> k= 0, 1, 2, 3;(m >= 2)
k=0 就是m 根 12的
k=1 因为 m>=2 ,m-=2; k=9; 就是m-2跟12的,3跟9的;
k=2;m--;k=6;
k=3;
beyondtkl 2004-12-25
  • 打赏
  • 举报
回复
GZ xuexi

我得算法太次了。。
pzcai 2004-12-25
  • 打赏
  • 举报
回复
如果要做的是3m不变了话,8M和10M就不用考虑了,肯定不节省的,剩下的是2根余1(7m),三根(9m),四根(12m)

要做的根数/4=(12m要的根数),要做的根数%4/3=(9m要的根数),(要做的根数%4%3+1)/2=(7m要的根数),
pzcai 2004-12-25
  • 打赏
  • 举报
回复
如果要做的是3m不变了话,8M和10M就不用考虑了,肯定不节省的,剩下的是2根余1(7m),三根(9m),四根(12m)

要做的根数/4=(12m要的根数),要做的根数%4/3=(9m要的根数),(要做的根数%4%3+1)/2=(12m要的根数),
加载更多回复(2)

3,882

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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