扬大算法实验.docx
《扬大算法实验.docx》由会员分享,可在线阅读,更多相关《扬大算法实验.docx(23页珍藏版)》请在冰豆网上搜索。
扬大算法实验
实验一:
电路板排列问题
//电路板排列问题回溯法求解
//#include"stdafx.h"
#include
#include
usingnamespacestd;
ifstreamfin("5d11.txt");
classBoard
{
friendintArrangement(int**B,intn,intm,intbestx[]);
private:
voidBacktrack(inti,intcd);
intn,//电路板数
m,//连接板数
*x,//当前解
*bestx,//当前最优解
bestd,//当前最优密度
*total,//total[j]=连接块j的电路板数
*now,//now[j]=当前解中所含连接块j的电路板数
**B;//连接块数组
};
template
inlinevoidSwap(Type&a,Type&b);
intArrangement(int**B,intn,intm,intbestx[]);
intmain()
{
intm=5,n=8;
intbestx[9];
inti,j;
//B={1,2,3,4,5,6,7,8}
//N1={4,5,6},N2={2,3},N3={1,3},N4={3,6},N5={7,8}
cout<<"m="<cout<<"N1={4,5,6},N2={2,3},N3={1,3},N4={3,6},N5={7,8}"<cout<<"二维数组B如下:
"<//构造B
int**B=newint*[n+1];
for(i=1;i<=n;i++)
{
B[i]=newint[m+1];
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
fin>>B[i][j];
cout<
}
cout<}
cout<<"当前最优密度为:
"<cout<<"最优排列为:
"<for(i=1;i<=n;i++)
{
cout<}
cout<for(i=1;i<=n;i++)
{
delete[]B[i];
}
delete[]B;
return0;
}
voidBoard:
:
Backtrack(inti,intcd)//回溯法搜索排列树
{intj,k;
if(i==n)
{
for(j=1;j<=n;j++)
{
bestx[j]=x[j];
}
bestd=cd;
}
else
{
for(j=i;j<=n;j++)
{
//选择x[j]为下一块电路板
intld=0;
for(k=1;k<=m;k++)
{
now[k]+=B[x[j]][k];
if(now[k]>0&&total[k]!
=now[k])
{
ld++;
}
}
//更新ld
if(cd>ld)
{
ld=cd;
}
if(ld{
Swap(x[i],x[j]);
Backtrack(i+1,ld);
Swap(x[i],x[j]);
//恢复状态
for(k=1;k<=m;k++)
{
now[k]-=B[x[j]][k];
}
}
}
}
}
intArrangement(int**B,intn,intm,intbestx[])
{
BoardX;
inti,j;
//初始化X
X.x=newint[n+1];
X.total=newint[m+1];
X.now=newint[m+1];
X.B=B;
X.n=n;
X.m=m;
X.bestx=bestx;
X.bestd=m+1;
//初始化total和now
for(i=1;i<=m;i++)
{
X.total[i]=0;
X.now[i]=0;
}
//初始化x为单位排列并计算total
for(i=1;i<=n;i++)
{
X.x[i]=i;
for(j=1;j<=m;j++)
{
X.total[j]+=B[i][j];
}
}
//回溯搜索
X.Backtrack(1,0);
delete[]X.x;
delete[]X.total;
delete[]X.now;
returnX.bestd;
}
template
inlinevoidSwap(Type&a,Type&b)
{
Typetemp=a;
a=b;
b=temp;
}
运行结果:
实验二:
连续邮资问题
#include
usingnamespacestd;
classStamp
{
friendintMaxStamp(int,int,int[]);
private:
intBound(inti);
voidBacktrack(inti,intr);
intn;//邮票面值数
intm;//每张信封最多允许贴的邮票数
intmaxvalue;//当前最优值
intmaxint;//大整数
intmaxl;//邮资上界
int*x;//当前解
int*y;//贴出各种邮资所需最少邮票数
int*bestx;//当前最优解
};
voidStamp:
:
Backtrack(inti,intr)
{
for(intj=0;j<=x[i-2]*(m-1);j++)
if(y[j]for(intk=1;k<=m-y[j];k++)
if(y[j]+ky[j+x[i-1]*k]=y[j]+k;
while(y[r]r++;
if(i>n){
if(r-1>maxvalue){
maxvalue=r-1;
for(intj=1;j<=n;j++)
bestx[j]=x[j];
}
return;
}
int*z=newint[maxl+1];
for(intk=1;k<=maxl;k++)
z[k]=y[k];
for(j=x[i-1]+1;j<=r;j++){
x[i]=j;
Backtrack(i+1,r);
for(intk=1;k<=maxl;k++)
y[k]=z[k];
}
delete[]z;
}
intMaxStamp(intn,intm,intbestx[]){
StampX;
intmaxint=32767;
intmaxl=1500;
X.n=n;
X.m=m;
X.maxvalue=0;
X.maxint=maxint;
X.maxl=maxl;
X.bestx=bestx;
X.x=newint[n+1];
X.y=newint[maxl+1];
for(inti=0;i<=n;i++)
X.x[i]=0;
for(i=1;i<=maxl;i++)
X.y[i]=maxint;
X.x[1]=1;
X.y[0]=0;
X.Backtrack(2,1);
cout<<"当前最优解:
";
for(i=1;i<=n;i++)
cout<cout<delete[]X.x;
delete[]X.y;
returnX.maxvalue;
}
voidmain(){
int*bestx;
intn;
intm;
cout<<"请输入邮票的个数:
";
cin>>n;
cout<<"请输入每张信封最多允许贴的邮票数:
";
cin>>m;
bestx=newint[n+1];
for(inti=1;i<=n;i++)
bestx[i]=0;
cout<<"最大邮资:
"<}
实验结果:
实验三:
0/1背包问题
#include
#include
intn;//物品数量
doublec;//背包容量
doublev[100];//各个物品的价值
doublew[100];//各个物品的重量
doublecw=0.0;//当前背包重量
doublecp=0.0;//当前背包中物品价值
doublebestp=0.0;//当前最优价值
doubleperp[100];//单位物品价值排序后
intorder[100];//物品编号
intput[100];//设置是否装入
//按单位价值排序
voidknapsack()
{
inti,j;
inttemporder=0;
doubletemp=0.0;
for(i=1;i<=n;i++)
perp[i]=v[i]/w[i];
for(i=1;i<=n-1;i++)
{
for(j=i+1;j<=n;j++)
if(perp[i]{
temp=perp[i];
perp[i]=perp[i];
perp[j]=temp;
temporder=order[i];
order[i]=order[j];
order[j]=temporder;
temp=v[i];
v[i]=v[j];
v[j]=temp;
temp=w[i];
w[i]=w[j];
w[j]=temp;
}
}
}
//回溯函数
voidbacktrack(inti)
{
doublebound(inti);
if(i>n)
{
bestp=cp;
return;
}
if(cw+w[i]<=c)
{
cw+=w[i];
cp+=v[i];
put[i]=1;
backtrack(i+1);
cw-=w[i];
cp-=v[i];
}
if(bound(i+1)>bestp)//符合条件搜索右子数
backtrack(i+1);
}
//计算上界函数
doublebound(inti)
{
doubleleftw=c-cw;
doubleb=cp;
while(i<=n&&w[i]<=leftw)
{
leftw-=w[i];
b+=v[i];
i++;
}
if(i<=n)
b+=v[i]/w[i]*leftw;
returnb;
}
intmain()
{
inti;
printf("请输入物品的数量和容量:
");
scanf("%d%lf",&n,&c);
printf("请输入物品的重量和价值:
");
for(i=1;i<=n;i++)
{
printf("第%d个物品的重量:
",i);
scanf("%lf",&w[i]);
printf("价值是:
");
scanf("%lf",&v[i]);
order[i]=i;
}
knapsack();
backtrack
(1);
printf("最有价值为:
%lf\n",bestp);
printf("需要装入的物品编号是:
");
for(i=1;i<=n;i++)
{
if(put[i]==1)
printf("%d",order[i]);
}
return0;
}
}
实验结果:
实验四:
旅行售货员问题
//5d9旅行员售货问题回溯法求解
//#include"stdafx.h"
#include
#include
usingnamespacestd;
ifstreamfin("5d9.txt");
constintN=4;//图的顶点数
template
classTraveling
{
template
friendTypeTSP(Type**a,intn);
private:
voidBacktrack(inti);
intn,//图G的顶点数
*x,//当前解
*bestx;//当前最优解
Type**a,//图G的领接矩阵
cc,//当前费用
bestc;//当前最优值
intNoEdge;//无边标记
};
template
inlinevoidSwap(Type&a,Type&b);
template
TypeTSP(Type**a,intn);
intmain()
{inti,j;
cout<<"图的顶点个数n="<int**a=newint*[N+1];
for(i=0;i<=N;i++)
{
a[i]=newint[N+1];
}
cout<<"图的邻接矩阵为:
"<for(i=1;i<=N;i++)
{
for(j=1;j<=N;j++)
{
fin>>a[i][j];
cout<}
cout<}
cout<<"最短回路的长为:
"<for(i=0;i<=N;i++)
{
delete[]a[i];
}
delete[]a;
a=0;
return0;
}
template
voidTraveling:
:
Backtrack(inti)
{
if(i==n)
{
if(a[x[n-1]][x[n]]!
=0&&a[x[n]][1]!
=0&&
(cc+a[x[n-1]][x[n]]+a[x[n]][1]{
for(intj=1;j<=n;j++)bestx[j]=x[j];
bestc=cc+a[x[n-1]][x[n]]+a[x[n]][1];
}
}
else
{
for(intj=i;j<=n;j++)
{
//是否可进入x[j]子树?
if(a[x[i-1]][x[j]]!
=0&&(cc+a[x[i-1]][x[i]]{
//搜索子树
Swap(x[i],x[j]);
cc+=a[x[i-1]][x[i]];//当前费用累加
Backtrack(i+1);//排列向右扩展,排列树向下一层扩展
cc-=a[x[i-1]][x[i]];
Swap(x[i],x[j]);
}
}
}
}
template
TypeTSP(Type**a,intn)
{inti,j;
TravelingY;
Y.n=n;
Y.x=newint[n+1];
Y.bestx=newint[n+1];
for(inti=1;i<=n;i++)
{
Y.x[i]=i;
}
Y.a=a;
Y.cc=0;
Y.bestc=0;
Y.NoEdge=0;
Y.Backtrack
(2);
cout<<"最短回路为:
"<for(inti=1;i<=n;i++)
{
cout<";
}
cout<delete[]Y.x;
Y.x=0;
delete[]Y.bestx;
Y.bestx=0;
returnY.bestc;
}
template
inlinevoidSwap(Type&a,Type&b)
{
Typetemp=a;
a=b;
b=temp;
}
运行结果:
实验五:
m着色问题
//#include"stdafx.h"
#include
#include
usingnamespacestd;
constintN=5;//图的顶点数
constintM=3;//色彩数
ifstreamfin("5d8.txt");
classColor{
friendintmColoring(int,int,int**);
private:
boolOk(intk);
voidBacktrack(intt);
intn,//图的顶点数
m,//可用的颜色数
**a,//图的邻接矩阵
*x;//当前解
longsum;//当前已找到的可m着色方案数
};
intmColoring(intn,intm,int**a);
intmain(){
inti,j;
int**a=newint*[N+1];
for(i=1;i<=N;i++){
a[i]=newint[N+1];
}
cout<<"图G的邻接矩阵为:
"<for(i=1;i<=N;i++){
for(j=1;j<=N;j++){
fin>>a[i][j];
cout<}
cout<}
cout<<"图G的着色方案如下:
"<cout<<"当m="<"<for(i=1;i<=N;i++){
delete[]a[i];
}
delete[]a;
}
voidColor:
:
Backtrack(intt)
{inti;
if(t>n){
sum++;
for(i=1;i<=n;i++)
cout<cout<}
else{
for(i=1;i<=m;i++){
x[t]=i;
if(Ok(t))Backtrack(t+1);
}}}
boolColor:
:
Ok(intk)//检查颜色可用性
{intj;
for(j=1;j<=n;j++){
if((a[k][j]==1)&&(x[j]==x[k])){//相邻且颜色相同
returnfalse;
}
}
returntrue;}
intmColoring(intn,intm,int**a){
ColorX;
inti;//初始化X
X.n=n;X.m=m;
X.a=a;X.sum=0;
int*p=newint[n+1];
for(i=0;i<=n;i++){
p[i]=0;
}
X.x=p;
X.Backtrack
(1);
delete[]p;
returnX.sum;
}
运行结果为: