日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

木材切割问题

發布時間:2024/1/23 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 木材切割问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

木材切割問題

一個木匠從木材公司買了一批木材,每塊木材的長度均相同,但由于制作家具時所需的木塊長度各不相同,因此需要把這些木材切割成長度不同的木塊。同時每次切割時由于鋸子本身有一定的寬度,因此每切割一次就會浪費掉一些木料。請設計一個程序使木匠能夠用最少的木材切割出所需的木塊。
輸入描述:
輸入有若干個測試樣例,每個測試樣例占一行。每行由若干個整數構成,第一個整數為所購買的木塊的長度L(0<L<=30000),第二個整數為鋸子的寬度W(0<W<=1000),其后的若干個整數分別表示制作家具時需要的木塊的長度。
輸出描述:
每個測試樣例輸出一行,為一個整數N,表示制作家具時需要購買的木塊的數量。

樣例輸入: 1000 100 250 250 500 650 1000 1000 50 200 250 250 500 650 970 樣例輸出: 3 4

代碼如下:

#include<stdio.h> #include<malloc.h> #include<cstring> #define MAX_SAMPLE_LENGTH 50 /*回溯法求解*///是一個數組,將輸入的木材尺寸保存至本數組 int*data=(int*)malloc(MAX_SAMPLE_LENGTH*sizeof(int)); //是一個布爾型數組,記錄當前木料的當前切割方法中,第i個木材是否被切割出來 bool*visited=(bool*)malloc(MAX_SAMPLE_LENGTH*sizeof(bool)); //是一個布爾型數組,記錄當前木料的最優切割方法中,第i個木材是否被切割出來 bool*nVisited=(bool*)malloc(MAX_SAMPLE_LENGTH*sizeof(bool)); //是一個布爾型數組,記錄木材是否已經被之前的木料切割出來 bool*res_arr=(bool*)malloc(MAX_SAMPLE_LENGTH*sizeof(bool)); int w;//原材料長度 int n;//數據元素個數 int sw;//鋸口寬度 int cw;//當前已鋸木頭長度和 int res;//求解結果 int bestW;//當前求解最大值//獲取輸入的函數 bool input(){bool flag=true;//初始化數據保存數組memset(visited,false,MAX_SAMPLE_LENGTH*sizeof(bool));memset(res_arr,false,MAX_SAMPLE_LENGTH*sizeof(bool));memset(nVisited,false,MAX_SAMPLE_LENGTH*sizeof(bool));//記錄輸入數據個數n=0;//讀取數據-原材料(木頭)長度scanf("%d",&w);if(0==w)flag=false;//鋸口寬度scanf("%d",&sw);while(flag){scanf("%d",data+n);n++;char ch=getchar();if(ch=='\n')break;}return flag; }//本函數用來計算每塊木料的最優切割算法 void backtrack(int i,int k){//當當前木料已經把所有之前木料未切割出來的木材遍歷完成,進入ifif(i>n-1){//如果當前切割方法切割出來的木材總長度大于之前的最優解,進入ifif(bestW<cw){//記錄最優值bestW=cw;//記錄當前最優解for(int i=0;i<n;i++){nVisited[i]=visited[i];}}return;}進入右子樹條件:若當前木材尺寸未被之前的木料切割出來且當前木料還有空余量可以切割出當前尺寸if(!res_arr[i]&&cw+data[i]+k*sw<=w){//記錄當前已鋸木頭數量k++;//進入右子樹實際操作cw+=data[i];//訪問標記visited[i]=true;//嵌套結構,計算data中下一個是否可在當前木料中被切割backtrack(i+1,k);//上一個樹枝已經判斷完了,退回上一個節點,拋棄上一種切割方法的最后一個節點,繼續判斷后面的木材是否可被切割。//假設共有5塊木材需要被切割,即data[0]-data[4],若上一種情況可被切割的木材為data[0],data[1],data[2],此處拋棄data[2],從這里 繼續遍歷,進行data[3]及之后的判斷。cw-=data[i];k--;}visited[i]=false;backtrack(i+1,k); }//本函數調用backtrack函數,用來計算需要多少塊木料 int solve(int*data,int n){res=0;//求解結果初始化int count=n;// count剩余未鋸木材數量,若存在未被切割的木材,則進入下一塊木料的切割,while的每一次循環代表一塊木料的切割。while(count>0){//初始化,cw當前已鋸木頭長度和,//count剩余未鋸木頭數量,bestW本次求解最大長度和cw=0,count=0,bestW=0;//調用backtrack函數,計算每一塊木料的最優解backtrack(0,0);for(int i=0;i<n;i++){更新待解決問題狀態:如果第i塊木材未被之前的木料切割出,則將第i塊木材是否被切割的狀態更新為當前木料的切割情況。if(!res_arr[i])res_arr[i]=nVisited[i];//計算剩余未切割出的木材的個數if(!res_arr[i])count++;}//記錄求解結果res++;}return res; }void main(){while(input()){solve(data,n);printf("\n%d\n",res);} }

附上該程序的debug視頻,幫助理解整個運行過程:
https://www.bilibili.com/video/BV155411J7sz

解空間樹如下圖:

總結

以上是生活随笔為你收集整理的木材切割问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。