计算机算法分析与设计第四版习题算法分析部分详解实验六.docx
《计算机算法分析与设计第四版习题算法分析部分详解实验六.docx》由会员分享,可在线阅读,更多相关《计算机算法分析与设计第四版习题算法分析部分详解实验六.docx(24页珍藏版)》请在冰豆网上搜索。
计算机算法分析与设计第四版习题算法分析部分详解实验六
实验六分支限界法
//6-1、6-6项目VC++6.0测试通过
//6-15项目VC2005测试通过
//6-1最小长度电路板排列问题
//头文件stdafx.h
//stdafx.h:
includefileforstandardsystemincludefiles,
//orprojectspecificincludefilesthatareusedfrequently,but
//arechangedinfrequently
//
#pragmaonce
#defineWIN32_LEAN_AND_MEAN//Excluderarely-usedstufffromWindowsheaders
#include
#include
//TODO:
referenceadditionalheadersyourprogramrequireshere
//sy61.cpp:
Definestheentrypointfortheconsoleapplication.
//
//Description:
//分支限界法6_1最小长度电路板排列问题
//#include"my.h"
#include"stdafx.h"
#include
#include
usingnamespacestd;
intn,m;
//#include"OutOfBounds.h"
//定义节点类
classBoardNode{
friendintFIFOBoards(int**,int,int,int*&);//非类成员,可以访问私有成员的函数,最优序列查找
public:
operatorint()const{returncd;}//返回常数cd
intlen();
public:
int*x,s,cd,*low,*high;//x表示当前节点的电路板排列,s表示当前节点排列好的电路板的数
//表示当前节点的最大长度,low,high分别表当前节点表示每一个连接块的第一个,和最后一个电路板
//的位置
};
//编写类的len()函数,求出当前节点的连接块长度的最大值
intBoardNode:
:
len()
{
inttmp=0;
for(intk=1;k<=m;k++)
if(low[k]<=n&&high[k]>0&&tmptmp=high[k]-low[k];
returntmp;
}
intFIFIOBoards(int**B,intn,intm,int*&bestx)//n为电路板的数量,m为连接块的数量
{
//intbestd;
queueq;//声明BoardNode类的节点队列q
BoardNodeE;
E.x=newint[n+1];//为数组指针x分配n+1个动态空间,存储当前的排列
E.s=0;//最初时,排列好的电路板的数目为0
E.cd=0;
E.low=newint[m+1];//存储每个连接块的第一个电路板的位置
E.high=newint[m+1];//存储每个连接块的最后一个电路板的位置
for(inti=1;i<=m;i++)
{
E.high[i]=0;//初始化开始时的每个连接块的最后一个电路板的位置为0,表示连接块i还没有电路板放入E.x的排列中
E.low[i]=n+1;//初始化开始时的每个连接块的第一个电路板的位置为n+1,表示连接块i还没有电路板放入E.x的排列中
}
for(i=1;i<=n;i++)
E.x[i]=i;//初始化E.x的排列为1,2,3.....n
intbestd=n+1;//最优距离
bestx=0;//记录当前最优排列
do{
if(E.s==n-1)//当已排列了n-1个时
{
//判断是否改变每个连接块的最后一个电路板的位置
for(intj=1;j<=m;j++)
if(B[E.x[n]][j]&&n>E.high[j])
E.high[j]=n;
intld=E.len();//存储当前节点的各连接块长度中的最大长度
//如果当前的最大长度小于了n+1
if(ld{
delete[]bestx;
bestx=E.x;
bestd=ld;//最优距离
}
elsedelete[]E.x;//删除分配给E.x的数组空间
delete[]E.low;//删除分配给E.low的数组空间
delete[]E.high;//删除分配给E.high的数组空间
}
else
{
intcurr=E.s+1;//rr记录现在应该排列第几个电路板
for(inti=E.s+1;i<=n;i++)//处理扩展节点下一层所有子节点
{
BoardNodeN;
N.low=newint[m+1];//与if中的意思相同
N.high=newint[m+1];
for(intj=1;j<=m;j++)
{
N.low[j]=E.low[j];//将E.low[]中的值赋给N.low[]
N.high[j]=E.high[j];
if(B[E.x[i]][j])
{
if(currN.low[j]=curr;//若当前节点连接块j的第一个电路板的位置比现在正在排列的电路板的位置还小
if(curr>N.high[j])
N.high[j]=curr;
}
}
N.cd=N.len();
//如果,当前节点的最大长度小于了最优长度则:
if(N.cd{
N.x=newint[n+1];
N.s=E.s+1;
for(intj=1;j<=n;j++)
N.x[j]=E.x[j];
N.x[N.s]=E.x[i];//交换位置
N.x[i]=E.x[N.s];//交换位置
q.push(N);//将节点N加入队列中
}
else
{
delete[]N.low;
delete[]N.high;
}
//printf("%d",bestd);
}
delete[]E.x;//当前扩展节点所有子节点均考虑,变成死结点
}
//try{
if(!
q.empty()){
E=q.front();//取队列首节点作为扩展节点
q.pop();
}elsereturnbestd;
//}
//catch(OutOfBounds)
//{
//returnbestd;
//}
//printf("finish");
}while(!
q.empty());
returnbestd;
return1;
}
//测试
voidmain()
{
//scanf("%d%d",&n,&m);
cin>>n>>m;
int**B=newint*[n+1];
for(intt=0;t<=n;t++)
B[t]=newint[m+1];
for(inti=1;i<=n;i++)
for(intj=1;j<=m;j++)
cin>>B[i][j];
//scanf("%d",&B[i][j]);
int*bestx=newint[n+1];
intbestd=0;
bestd=FIFIOBoards(B,n,m,bestx);
printf("%d\n",bestd);
for(i=1;i<=n;i++){
cout<}
cout<}
//6-6经典n皇后问题
//Description:
经典n皇后问题广度优先建议n<=14解空间为子集树
//参考答案说排列树是不正确的,本例打印n*n棋盘的所有解,即放置方法
#include
#include
#include
#include
#include
usingnamespacestd;
//本例子直接输入棋盘大小,不用文件
//ifstreamin("input.txt");//请在项目文件夹下新建一个input.txt
//ofstreamout("output.txt");
classNode{
public:
Node(intn){
t=0;
this->n=n;
loc=newint[n+1];
for(inti=0;i<=n;++i)
{
loc[i]=0;
}
}
Node(constNode&other){
this->t=other.t;
this->n=other.n;
this->loc=newint[n+1];
for(inti=0;i<=n;++i){
this->loc[i]=other.loc[i];
}
}
intt;//已放置t个皇后
int*loc;//loc[1:
t]
intn;//共放置n个皇后
boolcheckNext(intnext);
voidprintQ();
};
boolNode:
:
checkNext(intnext){
inti;
for(i=1;i<=t;++i)
{
if(loc[i]==next)//检测同列
{
returnfalse;
}
if(loc[i]-next==t+1-i)//检测反斜线行差==列差
{
returnfalse;
}
if(loc[i]-next==i-t-1)//检测正斜线
{
returnfalse;
}
}
returntrue;
}
voidNode:
:
printQ(){
for(inti=1;i<=n;++i)
{
cout<}
cout<}
classQueen{
public:
intn;//n皇后
intansNum;//对于n皇后解的个数
Queen(intn){
this->n=n;
ansNum=0;
}
voidArrangQueen();
};
voidQueen:
:
ArrangQueen(){
queueQ;
Nodeini(n);//初始化
Q.push(ini);
while(!
Q.empty()){
Nodefather=Q.front();//取队列下一个节点
Q.pop();
if(father.t==n)
{
father.printQ();
++ansNum;
}
for(inti=1;i<=n;++i)//一次性将当前扩展节点所有子节点考虑完,符合条件的插入队列
{
if(father.checkNext(i))
{
NodeChild(father);
++Child.t;
Child.loc[Child.t]=i;
Q.push(Child);
}
}
}
}
intmain(){
//#defineincin
//#defineoutcout
cout<<"请输入棋盘大小n:
";
intn;
cin>>n;//从文件中读入一个整数
//for(intCase=1;Case<=cases;++Case){
//intn;
//in>>n;
QueenQ(n);
Q.ArrangQueen();
//out<<"Case#"<"<cout<<"共"<"<//}
return0;
}
//6-15排列空间树问题VC2005测试通过
//stdafx.h头文件
//stdafx.h:
includefileforstandardsystemincludefiles,
//orprojectspecificincludefilesthatareusedfrequently,but
//arechangedinfrequently
//
#pragmaonce
#defineWIN32_LEAN_AND_MEAN//Excluderarely-usedstufffromWindowsheaders
#include
#include
//TODO:
referenceadditionalheadersyourprogramrequireshere
//头文件MinHeap2.h;最小堆实现
#include
template
classGraph;
template
classMinHeap
{
template
friendclassGraph;
public:
MinHeap(intmaxheapsize=10);
~MinHeap(){delete[]heap;}
intSize()const{returncurrentsize;}
TMax(){if(currentsize)returnheap[1];}
MinHeap&Insert(constT&x);
MinHeap&DeleteMin(T&x);
voidInitialize(Tx[],intsize,intArraySize);
voidDeactivate();
voidoutput(Ta[],intn);
private:
intcurrentsize,maxsize;
T*heap;
};
template
voidMinHeap:
:
output(Ta[],intn)
{
for(inti=1;i<=n;i++)
cout<cout<}
template
MinHeap:
:
MinHeap(intmaxheapsize)
{
maxsize=maxheapsize;
heap=newT[maxsize+1];
currentsize=0;
}
template
MinHeap&MinHeap:
:
Insert(constT&x)
{
if(currentsize==maxsize)
{
return*this;
}
inti=++currentsize;
while(i!
=1&&x{
heap[i]=heap[i/2];
i/=2;
}
heap[i]=x;
return*this;
}
template
MinHeap&MinHeap:
:
DeleteMin(T&x)
{
if(currentsize==0)
{
cout<<"Emptyheap!
"<return*this;
}
x=heap[1];
Ty=heap[currentsize--];
inti=1,ci=2;
while(ci<=currentsize)
{
if(ciheap[ci+1])
{
ci++;
}
if(y<=heap[ci])
{
break;
}
heap[i]=heap[ci];
i=ci;
ci*=2;
}
heap[i]=y;
return*this;
}
template
voidMinHeap:
:
Initialize(Tx[],intsize,intArraySize)
{
delete[]heap;
heap=x;
currentsize=size;
maxsize=ArraySize;
for(inti=currentsize/2;i>=1;i--)
{
Ty=heap[i];
intc=2*i;
while(c<=currentsize)
{
if(cheap[c+1])
c++;
if(y<=heap[c])
break;
heap[c/2]=heap[c];
c*=2;
}
heap[c/2]=y;
}
}
template
voidMinHeap:
:
Deactivate()
{
heap=0;
}
//批作业调度问题优先队列分支限界法求解
//算法编码与教材一致
#include"stdafx.h"
#include"MinHeap2.h"
#include
usingnamespacestd;
classFlowshop;
classMinHeapNode
{
friendFlowshop;
public:
operatorint()const
{
returnbb;
}
private:
voidInit(int);
voidNewNode(MinHeapNode,int,int,int,int);
ints,//已安排作业数
f1,//机器1上最后完成时间
f2,//机器2上最后完成时间
sf2,//当前机器2上完成时间和
bb,//当前完成时间和下界
*x;//当前作业调度
};
classFlowshop
{
friendintmain(void);
public:
intBBFlow(void);
private:
intBound(MinHeapNodeE,int&f1,int&f2,bool**y);
voidSort(void);
intn,//作业数
**M,//各作业所需的处理时间数组
**b,//各作业所需的处理时间排序数组
**a,//数组M和b的对应关系数组
*bestx,//最优解
bestc;//最小完成时间和
bool**y;//工作数组
};
template
inlinevoidSwap(Type&a,Type&b);
intmain()
{
intn=3,bf;
intM1[3][2]={{2,1},{3,1},{2,3}};
int**M=newint*[n];
int**b=newint*[n];
int**a=newint*[n];
bool**y=newbool*[n];
int*bestx=newint[n];
for(inti=0;i<=n;i++)
{
M[i]=newint[2];
b[i]=newint[2];
a[i]=newint[2];
y[i]=newbool[2];
}
cout<<"各作业所需要的时间处理数组M(i,j)值如下:
"<for(inti=0;i{
for(intj=0;j<2;j++)
{
M[i][j]=M1[i][j];
}
}
for(inti=0;i{
cout<<"(";
for(intj=0;j<2;j++)
cout<cout<<")";
}
cout<Flowshopflow;
flow.n=n;
flow.M=M;
flow.b=b;
flow.a=a;
flow.y=y;
flow.bestx=bestx;
flow.bestc=1000;//给初值
flow.BBFlow();
cout<<"最优值是:
"<