分配問題-分支限界法
阿新 • • 發佈:2019-02-16
// branchBound_assignJob.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <iostream> #include <cstring> #include <vector> using namespace std; #define N 4 //case 1 --> N=5 //int c[][N]={ // 3, 8, 4, 12,16, // 9, 12, 13, 5,12, // 8, 7, 9, 3,10, // 12, 7, 6, 8,11, // 23, 17, 26, 18, 13 //}; //case 2 --> N=4 int c[][N]={ 3, 8, 4, 12, 9, 12, 13, 5, 8, 7, 9, 3, 12, 7, 6, 8 }; //case 3 --> N=3 //int c[][N]={ // 4, 3, 2, // 2, 4, 6, // 8, 7, 5 //}; int costBoundInK = 65535;//搜尋深度為k時的花費下界,深度為k有N-k個節點的下界,取最小值給minCostInk int minCostInk = 65535;//搜尋深度為k時的最小下界 int minCostLine = 0;//記錄最小下界節點所在的行 int expanded[N];//存放被擴充套件節點的順序 vector<int> vectors;//存放搜尋深度為k時的花費下界,即costBoundInK int min_exceptiInRow(int i,int row) { int min = 65535; for (int line=0; line<N; line++) { bool currExpanded =false; for (int m=0;m<N;m++) { if (expanded[m] == line)//line行的某一節點已經之前被擴充套件過,故這一行的節點不能再擴充套件 { currExpanded = true; break; } } //功能:除去當前行和之前被擴充套件的節點所在行之後,通過迴圈找出row這列的最小值 if (line!=i && !currExpanded && c[line][row]<min)//與i不在同一行,同時節點未被擴充套件,且是這一列中的最小值 { min = c[line][row]; } } return min; } /************************************************************************ **功能:求出最小的花費 **引數:k為作業編號 mincost為最終返回的最小花費 ************************************************************************/ void branchBound(int k,int& mincost) { while(true) { if (k<N)//未到葉子節點 { bool currExpanded = false; minCostInk = 65535; for (int i=0; i<N; i++) { for (int m=0;m<N;m++) { if (expanded[m]==i)//檢視當前行的某一節點是否已經被擴充套件過,若擴充套件過,則當前行的所有節點都不能再擴充套件 { currExpanded = true; break; } } if (!currExpanded)//當前行未被擴充套件 { costBoundInK = c[i][k];//costBoundInK表示在某個搜尋深度k下,把作業k分配給工人i時的時間下界 for (int j=k+1;j<N;j++) { costBoundInK += min_exceptiInRow(i,j);//深度k下的花費下界,即在未擴充套件節點所在列均取花費的最小值,並累加 } if (costBoundInK < minCostInk) { minCostInk = costBoundInK; minCostLine = i; //記錄要擴充套件節點的行號 expanded[k] = i; //expanded[k]記錄花費矩陣中節點被擴充套件的順序,k為列,代表作業編號,依次為0,1...N //對應的i為行,代表工人編號,即分配方案為工人i完成作業k } vectors.push_back(costBoundInK);//不同深度k下計算的花費下界存入vectors容器;深度為k時,需要計算N-k次下界,取最小值為擴充套件節點 } currExpanded = false; expanded[k]=-1;//同級節點擴充套件,恢復當前節點為未擴充套件 } expanded[k] = minCostLine;//選取當前搜尋深度k下,花費最少的為擴充套件節點c[minCostLine][k] k++; } else//到達葉節點 { for(int i=0;i<N;i++)//根據擴充套件節點的順序,計算最小花費 { mincost +=c[expanded[i]][i]; } break; } } } int main(int argc, char *argv[]) { memset(expanded, -1, N*sizeof(int));//給陣列置-1 int mincost=0; branchBound(0,mincost);//分支限界演算法,從根節點開始擴充套件,由mincost返回最少花費 //輸出 cout<<"-------花費矩陣(行為工人,列為作業,從0開始)----------"<<endl; for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { printf("%3d ",c[i][j]); } cout << endl; } cout<<"---------------------------------------------"<<endl; for(int i=0;i<N;i++) { cout<< "作業:" << i << " --> 由工人" << expanded[i] << "完成. "<< " 花費為:" << c[expanded[i]][i] << " " << endl; } cout << "總花費為:"<< mincost<< endl; return 0; }