是一个算法问题,大伙有没有什么好的解法或意见.大板尺寸:3070*1410  单位:豪米划分成: 
150*100 2500件
50*50   1000件
100*50  2000件
刀路为:3mm
 
所需总面积:153*103*2500+53*53*1000+103*53*2000 平方豪米问题:需要几块大板,才是损耗最小的方案。计算得出:大约需要14块大板~但这样必须做到除了刀路损耗之外,绝对不许出现其它损耗,问题就在这里了~怎样才能做到?正在开发一个C#的Winform,这个难点把我折磨的够苦了~希望有高人指点下~

解决方案 »

  1.   

    这种包裹问题太多了——基本上都是无解,仁者见仁智者见智
    贪心算法
    贪心算法一、算法思想贪心法的基本思路:
    --从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到某算法中的某一步不能再继续前进时,算法停止。
    该算法存在问题:
    1. 不能保证求得的最后解是最佳的;
    2. 不能用来求最大或最小解问题;
    3. 只能求满足某些约束条件的可行解的范围。
    实现该算法的过程:
    从问题的某一初始解出发;
    while 能朝给定总目标前进一步 do
       求出可行解的一个解元素;
    由所有解元素组合成问题的一个可行解;二、例题分析1、[背包问题]有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。
    要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。物品 A  B  C D E F G 
    重量 35  30  60  50  40  10  25  
    价值  10  40  30 50  35  40  30 
    分析:目标函数: ∑pi最大
    约束条件是装入的物品总重量不超过背包容量:∑wi<=M( M=150)
    (1)根据贪心的策略,每次挑选价值最大的物品装入背包,得到的结果是否最优?
    (2)每次挑选所占空间最小的物品装入是否能得到最优解?
    (3)每次选取单位容量价值最大的物品,成为解本题的策略。 ? 
    马踏棋盘的贪心算法
    123041-23 XX【问题描述】
    马的遍历问题。在8×8方格的棋盘上,从任意指定方格出发,为马寻找一条走遍棋盘每一格并且只经过一次的一条路径。
    【初步设计】
    首先这是一个搜索问题,运用深度优先搜索进行求解。算法如下:
    1、 输入初始位置坐标x,y;
    2、 步骤 c:
       如果c>64输出一个解,返回上一步骤c--
    (x,y) ← c
    计算(x,y)的八个方位的子结点,选出那此可行的子结点
    循环遍历所有可行子结点,步骤c++重复2
    显然(2)是一个递归调用的过程,大致如下:
    void dfs(int x,int y,int count)
    {
    int i,tx,ty;
    if(count>N*N)
    {
    output_solution();//输入一个解
    return;
    }
    for(I=0;i<8;++i)
    {
    tx=hn[i].x;//hn[]保存八个方位子结点
    ty=hn[i].y;
    s[tx][ty]=count;
    dfs(tx,ty,count+1);//递归调用
    s[tx][ty]=0;
    }
    }
    这样做是完全可行的,它输入的是全部解,但是马遍历当8×8时解是非常之多的,用天文数字形容也不为过,这样一来求解的过程就非常慢,并且出一个解也非常慢。
    怎么才能快速地得到部分解呢?
    【贪心算法】
    其实马踏棋盘的问题很早就有人提出,且早在1823年,J.C.Warnsdorff就提出了一个有名的算法。在每个结点对其子结点进行选取时,优先选择‘出口’最小的进行搜索,‘出口’的意思是在这些子结点中它们的可行子结点的个数,也就是‘孙子’结点越少的越优先跳,为什么要这样选取,这是一种局部调整最优的做法,如果优先选择出口多的子结点,那出口少的子结点就会越来越多,很可能出现‘死’结点(顾名思义就是没有出口又没有跳过的结点),这样对下面的搜索纯粹是徒劳,这样会浪费很多无用的时间,反过来如果每次都优先选择出口少的结点跳,那出口少的结点就会越来越少,这样跳成功的机会就更大一些。这种算法称为为贪心算法,也叫贪婪算法或启发示算法,它对整个求解过程的局部做最优调整,它只适用于求较优解或者部分解,而不能求最优解。这样的调整方法叫贪心策略,至于什么问题需要什么样的贪心策略是不确定的,具体问题具体分析。实验可以证明马遍历问题在运用到了上面的贪心策略之后求解速率有非常明显的提高,如果只要求出一个解甚至不用回溯就可以完成,因为在这个算法提出的时候世界上还没有计算机,这种方法完全可以用手工求出解来,其效率可想而知。
    在前面的算法基础之上,增添一些程序加以实现:
    函数1:计算结点出口多少
    int ways_out(int x,int y)
    {
    int i,count=0,tx,ty;
    if(x<0||y<0||x>=N||y>=N||s[x][y]>0)
    return -1;//-1表示该结点非法或者已经跳过了
    for(i=0;i<8;++i)
    {
    tx=x+dx[i];
    ty=y+dy[i];
    if(tx<0||ty<0||tx>=N||ty>=N)
    continue;
    if(s[tx][ty]==0)
    ++count;
    }
    return count;
    }
    函数2:按结点出口进行排序
    void sortnode(h_node *hn,int n)//采用简单排序法,因为子结点数最多只有8
    {
    int i,j,t;
    h_node temp;
    for(i=0;i<n;++i)
    {
    for(t=i,j=i+1;j<n;++j)
    if(hn[j].waysout<hn[t].waysout)
    t=j;
    if(t>i)
    {
    temp=hn[i];
    hn[i]=hn[t];
    hn[t]=temp;
    }
    }
    }
    函数3:修改后的搜索函数
    void dfs(int x,int y,int count)
    {
    int i,tx,ty;
    h_node hn[8];
    if(count>N*N)
    {
    output_solution();
    return;
    }
    for(i=0;i<8;++i)//求子结点和出口
    {
    hn[i].x=tx=x+dx[i];
    hn[i].y=ty=y+dy[i];
    hn[i].waysout=ways_out(tx,ty);
    }
    sortnode(hn,8);
    for(i=0;hn[i].waysout<0;++i);//不考虑无用结点
    for(;i<8;++i)
    {
    tx=hn[i].x;
    ty=hn[i].y;
    s[tx][ty]=count;
    dfs(tx,ty,count+1);
    s[tx][ty]=0;
    }
    }
    函数4:主调函数
    void main()
    {
    int i,j,x,y;
    for(i=0;i<N;++i)//初始化
    for(j=0;j<N;++j)
    s[i][j]=0;
    printf("Horse jump while N=%d\nInput the position to start:",N);
    scanf("%d%d",&x,&y);//输入初始位置
    while(x<0||y<0||x>=N||y>=N)
    {
    printf("Error! x,y should be in 0~%d",N-1);
    scanf("%d%d",&x,&y);
    }
    s[x][y]=1;
    dfs(x,y,2);//开始搜索
    }
    http://blog.csdn.net/cfreez/archive/2007/06/27/1668543.aspx
    普遍意义的背包是求总价值最大,这里我只讨论能背的总重量最大。为了便于理解,我通过一个具体的例子来说明有物品重量为{16,13,9,6,7,1,3,18} 背包能装的最大重量为51(1)先进行升序排列{1,3,6,7,9,13,16,18}(2)求得相邻数的差  2     3     1    2      4     3       2(3)对相邻数差分组并将得到的数按升序排列,于是有下结果差为1        6-7差为2       1-3  ,7-9, 16-18差为3      3-6,13-16差为4      9-13(4)从最大的差组最大的数往下加,如果大于总重则跳过,直到到达最小值为止,并计算出其差值   得到数列为  13,9,16,6,3,18,7,1      13+9 +16+6+3+1=48               51-48=3差值为3(5)找到小于或等于差值的组,从差最大的组找起,找到前缀在其中的数,并置换在差为3组中找到13-16,3-6 但是16,6已在其中,于是往下找在差为2组中找到16-18,替换13 + 9 +18 + 6 +3 +1 =50  51-50=1在差为1组中找到6-7,替换13 + 9 +18 + 7 +3 +1 =50结束这种算法我称为“序差置换法” 
    ==================================================================
    博客空间:http://blog.csdn.net/lovingkiss
    资源下载:http://download.csdn.net/user/lovingkiss
    Email:loving-kiss@163.com
    本人说明:<我的帖子我做主,结贴率保持100%>
    优惠接单开发,信誉保证,Q64180940(请清楚注明业务还是技术咨询) 
    ==================================================================
      

  2.   

    //JavaK(舞月光),怎么到处放厥辞阿??这种算法,你能穷举么?——你以为这是买白菜呢,就那么三棵五棵的。类似的包裹问题——如果进行穷举,大型计算机跑个三年五载都未必出来,你能接受么??
    ==================================================================
    博客空间:http://blog.csdn.net/lovingkiss
    资源下载:http://download.csdn.net/user/lovingkiss
    Email:loving-kiss@163.com
    本人说明:<我的帖子我做主,结贴率保持100%>
    优惠接单开发,信誉保证,Q64180940(请清楚注明业务还是技术咨询) 
    ==================================================================