一、实验目的
理解并实践分支限界算法。
二、 实验要求
完成教材第6章8个应用范例中的至少3个(任选3个实现即可)。
三、实验步骤与结果
(1)布线问题:
代码:
#include<iostream>
#include<queue>
#include<fstream>
using namespace std;
ifstream fin("map.txt");
typedef struct Position
{
int row;
int col;
} Posi;
bool FindPath(Posi start,Posi finish,int & PathLen,int **&grid,Posi *& path,int n,int m)
{
if((start.row == finish.row) && (start.col == finish.col))
{
PathLen = 0;
return true;
}
Position offset[4];
offset[0].row = -1;
offset[0].col = 0;
offset[1].row = 1;
offset[1].col = 0;
offset[2].row = 0;
offset[2].col = -1;
offset[3].row = 0;
offset[3].col = 1;
Posi here,nbr;
here.row = start.row;
here.col = start.col;
int NumOfNbrs = 4;
grid[start.row][start.col] = 2;
queue<Posi> Q;
do
{
for(int firdex = 0;firdex < NumOfNbrs;firdex++)
{
nbr.row = here.row + offset[firdex].row;
nbr.col = here.col + offset[firdex].col;
if(grid[nbr.row][nbr.col] == 0)
{
grid[nbr.row][nbr.col] = grid[here.row][here.col] + 1;
if((nbr.row == finish.row) && (nbr.col == finish.col))
{
break;
}
Q.push(nbr);
}
}
if((nbr.row == finish.row) && (nbr.col ==finish.col))
{
break;
}
if(Q.empty())
{
return false;
}
here = Q.front();
Q.pop();
}while(true);
PathLen = grid[finish.row][finish.col]-2;
path = new Posi[PathLen];
here = finish;
for(int firdex = PathLen-1;firdex >=0;firdex--)
{
path[firdex] = here;
for(int secdex = 0;secdex < NumOfNbrs;secdex++)
{
nbr.row = here.row + offset[secdex].row;
nbr.col = here.col + offset[secdex].col;
if(grid[nbr.row][nbr.col] == firdex+2)
{
break;
}
}
here =nbr;
}
return true;
}
void InitGrid(int **&grid,int n,int m)
{
grid = new int*[n+2];
for(int firdex = 0;firdex < n+2;firdex++)
grid[firdex] = new int[m+2];
for(int index = 0;index < m+2;index++)
{
grid[0][index] = grid[n+1][index] =1;
}
for(int index = 0;index < n+2;index++)
{
grid[index][0] = grid[index][m+1] = 1;
}
for(int firdex = 1;firdex < n+1;firdex++)
{
for(int secdex = 1;secdex < m+1;secdex++)
fin>>grid[firdex][secdex];
}
}
void Destroy(int ** &grid,int n,int m)
{
if(grid != NULL)
{
for(int firdex = 0;firdex < n+2;firdex++)
{
delete [] grid[firdex];
grid[firdex] = NULL;
}
delete grid;
grid = NULL;
}
}
int main(void)
{
int m = 0,n = 0;
Posi start,finish;
int PathLength = 0;
Posi * path = NULL;
int ** grid = NULL;
cout<<"请输入网格长和宽:";
cin>>n>>m;
cout<<endl;
cout<<"请输入起点坐标:"<<endl;
cout<<"行号 = ";
cin>>start.row;
cout<<"列号 = ";
cin>>start.col;
cout<<endl;
cout<<"请输入终点坐标:"<<endl;
cout<<"行号 = ";
cin>>finish.row;
cout<<"列号 = ";
cin>>finish.col;
InitGrid(grid,n,m);
cout<<endl;
cout<<"网格(0表示可走,1不可走):"<<endl;
for(int firdex = 1;firdex < n+1;firdex++)
{
for(int secdex = 1;secdex < m+1;secdex++)
cout<<grid[firdex][secdex]<<" ";
cout<<endl;
}
cout<<endl;
FindPath(start,finish,PathLength,grid,path,n,m);
cout<<"最短路径耗费 :"<<PathLength<<endl;
cout<<"路线:"<<endl;
for(int index = 0;index < PathLength;index++)
{
cout<<"("<<path[index].row<<","<<path[index].col<<")";
if(index < PathLength-1)
cout<<"-->";
}
cout<<endl;
Destroy(grid,n,m);
if(path != NULL)
{
delete [] path;
path = NULL;
}
return 0;
}
结果:
(2)装载问题
代码:
#include<iostream>
using namespace std;
class Loading
{
friend float MaxLoading(float[],float,int);
public:
void Backtrack(int i); int n;
int *x,*bestx;
float *w,c,cw,bestw,r;
};
float Maxloading(float w1[],float c1,float c2,int n1,int bestx1[])
{
Loading k; int j;
float MAXLoad;
k.x= new int [n1+1];
k.bestx=bestx1;
k.w = w1;
k.c = c1;
k.n = n1; k.cw = 0;
k.bestw = 0;
k.r = 0;
for(int i=1;i<=n1;i++)
k.r+=w1[i];
k.Backtrack(1);
delete [] k.x;
cout<<endl;
cout<<"船1最优装载:"<<k.bestw<<endl;
MAXLoad=k.bestw;
for( j=1;j<=n1;j++)
{
if(k.bestx[j]==0)
{
MAXLoad+=w1[j]; c2-=w1[j]; if(c2<0)
{
cout<<"找不到合理装载方案!"<<endl;
return -1;
}
}
}
cout<<"船1中的箱子:";
for(j=1;j<=n1;j++)
if(k.bestx[j]==1)
cout<<j<<" ";
cout<<endl;
cout<<"船2中的箱子:";
for(j=1;j<=n1;j++)
if(k.bestx[j]==0)
cout<<j<<" ";
cout<<endl;
return MAXLoad;
}
void Loading::Backtrack(int i)
{
if(i>n)
{
if(cw>bestw)
{
for(int j=1;j<=n;j++)
bestx[j]=x[j];
bestw = cw;
}
return;
}
r-=w[i];
if(cw+w[i]<=c)
{
x[i]=1;
cw+=w[i];
Backtrack(i+1);
cw-=w[i];
}
if(cw+r>bestw)
{
x[i] = 0;
Backtrack(i+1);
}
r+=w[i];
}
int main()
{
float w[20];
float c1,c2,k;
int n,bestx[20];
cout<<"输入箱子数:";
cin>>n;
cout<<"输入箱子重量:";
for(int i=1;i<=n;i++)
cin>>w[i];
cout<<"输入容量船1,船2:";
cin>>c1>>c2;
k=Maxloading(w,c1,c2,n,bestx);
if(k!=-1)
cout<<"总体最优装载:"<<k<<endl;
return 1;
}
结果:
(3)最大团问题
代码:
#include <iostream>
#include <cstring>
using namespace std;
const int maxnum=101;
bool a[maxnum][maxnum];
bool x[maxnum];
int cn;
int bestn;
int n;
int e;
void backtrack(int i)
{
int j;
if(i>n)
{
bestn=cn;
cout<<endl;
cout<<"顶点数:"<<bestn<<endl;
cout<<"顶点编号:";
for(j=1; j<=n; j++)
{
if(x[j])
{
cout<<j<<" ";
}
}
cout<<endl;
return ;
}
bool ok=true;
for(j=1; j<i; j++)
{
if(x[j]&&!a[j][i])
{
ok=false;
break;
}
}
if(ok)
{
cn++;
x[i]=true;
backtrack(i+1);
cn--;
}
if(cn+n-i>bestn)
{
x[i]=false;
backtrack(i+1);
}
}
int main()
{
int i,u,v;
memset(a,false,sizeof(a));
memset(x,false,sizeof(x));
cout<<"请输入顶点数和边数:";
cin>>n>>e;
for(i=0; i<e; i++)
{
cout<<"边"<<i+1<<":";
cin>>u>>v;
a[u][v]=true;
a[v][u]=true;
}
cn=bestn=0;
backtrack(1);
return 0;
}
结果: