最大字段和实验报告.docx
《最大字段和实验报告.docx》由会员分享,可在线阅读,更多相关《最大字段和实验报告.docx(15页珍藏版)》请在冰豆网上搜索。
最大字段和实验报告
最大字段和
1.实验目的和要求
(1)深刻掌握动态规划法的设计思想并能熟练运用;
(2)理解这样一个观点:
同样的问题可以用不同的方法解决,一个好的算法是反复努力和重新修正的结果。
(3)分别用蛮力法、分治法和动态规划法设计最大子段和问题的算法;
(4)比较不同算法的时间性能;
(5)给出测试数据,写出程序文档
2.实验内容
给定由n个整数组成的序列(a1,a2,…,an),求该序列形如的子段和的最大值,当所有整数均为负整数时,其最大子段和为0。
3.实验环境
TurboC或VC++
4.实验学时
2学时,必做实验
5.数据结构与算法
数据结构:
程序中所用的数据都是储存在数组当中
算法:
蛮力法函数MaxSum(inta[],intn,int&besti,int&bestj)
分治法函数MaxSum(inta[],intleft,intright)
动态规划法函数MaxSum(intn,inta[])
6.核心源代码及时间性能分析
(1)蛮力法:
#include
intMaxSum(inta[],intn,int&besti,int&bestj)
{
intsum=0;
inti,j,k;
for(i=1;i<=n;i++)
{
intasum=0;
for(j=i;j<=n;j++)
{
asum+=a[j];
if(asum>sum)
{
sum=asum;
besti=i;
bestj=j;
}
}
}
returnsum;
}
voidmain()
{
intn,a[
cout<<"请输入各元素的值(一共"<100],m,i,j,maxsum;
cout<<"请输入整数序列的元素个数n:
"<cin>>n;
"<for(m=1;m<=n;m++)
cin>>a[m];
maxsum=MaxSum(a,n,i,j);
cout<<"整数序列的最大子段和是:
"<}
时间性能:
T(n)=O(n²)
结果截图:
(2)分治法:
#include
intMaxSum(inta[],intleft,intright)
{
intsum=0;
if(left==right)
{
if(a[left]>0)
sum=a[left];
else
sum=0;
}
else
{
intcenter=(left+right)/2;
intleftsum=MaxSum(a,left,center);
intrightsum=MaxSum(a,center+1,right);
ints1=0;
intlefts=0;
for(inti=center;i>=left;i--)
{
lefts+=a[i];
if(lefts>s1)
s1=lefts;
}
ints2=0;
intrights=0;
for(intj=center+1;j<=right;j++)
{
rights+=a[j];
if(rights>s2)
s2=rights;
}
sum=s1+s2;
if(sumif(sum}
returnsum;
}
voidmain()
{
intn,a[100],m,maxsum;
cout<<"请输入整数序列的元素个数n:
"<cin>>n;
cout<<"请输入各元素的值(一共"<"<for(m=1;m<=n;m++)
cin>>a[m];
maxsum=MaxSum(a,1,n);
cout<<"整数序列的最大子段和是:
"<}
时间性能:
T(n)=O(nlog2(n))
结果截图:
(3)动态规划法:
#include
voidMaxSum(intn,inta[])
{
intsum=0;
intb=0;
for(inti=1;i<=n;i++)
{
if(b>0)
b+=a[i];
else
b=a[i];
if(b>sum)
sum=b;
}
cout<<"整数序列的最大子段和是:
"<}
voidmain()
{
intn,a[100],m,maxsum;
cout<<"请输入整数序列的元素个数n:
"<cin>>n;
cout<<"请输入各元素的值(一共"<"<for(m=1;m<=n;m++)
cin>>a[m];
MaxSum(n,a);
}
时间性能:
T(n)=O(n)
结果截图:
背包问题
1.实验题目:
分别用贪心法法和分支限界法求解背包问题
2.实验内容:
0-1背包问题:
给定n种物品和一个背包。
物品i的重量是Wi,其价值为Vi,背包的容量为C。
应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包或不装入背包。
不能将物品i装入背包多次,也不能只装入部分的物品i。
3.实验源程序:
(1)贪心法:
#include
structgoodinfo
{
floatp;//物品效益
floatw;//物品重量
floatX;//物品该放的数量
intflag;//物品编号
};//物品信息结构体
voidInsertionsort(goodinfogoods[],intn)
{
intj,i;
for(j=2;j<=n;j++)
{
goods[0]=goods[j];
i=j-1;
while(goods[0].p>goods[i].p)
{
goods[i+1]=goods[i];
i--;
}
goods[i+1]=goods[0];
}
}//按物品效益,重量比值做升序排列
voidbag(goodinfogoods[],floatM,intn)
{
floatcu;
inti,j;
for(i=1;i<=n;i++)
goods[i].X=0;
cu=M;//背包剩余容量
for(i=1;i{
if(goods[i].w>cu)//当该物品重量大与剩余容量跳出
break;
goods[i].X=1;
cu=cu-goods[i].w;//确定背包新的剩余容量
}
if(i<=n)
goods[i].X=cu/goods[i].w;//该物品所要放的量
/*按物品编号做降序排列*/
for(j=2;j<=n;j++)
{
goods[0]=goods[j];
i=j-1;
while(goods[0].flag{
goods[i+1]=goods[i];
i--;
}
goods[i+1]=goods[0];
}
cout<<"最优解为:
"<for(i=1;i<=n;i++)
{
cout<<"第"<
";
cout<}
}
voidmain()
{
cout<<"|--------运用贪心法解背包问题---------|"<cout<<"|---powerby李奇蓬---|"<cout<<"|-------------------------------------|"<intj;
intn;
floatM;
goodinfo*goods;//定义一个指针
while(j)
{
cout<<"请输入物品的总数量:
";
cin>>n;
goods=newstructgoodinfo[n+1];//
cout<<"请输入背包的最大容量:
";
cin>>M;
cout<inti;
for(i=1;i<=n;i++)
{goods[i].flag=i;
cout<<"请输入第"<
";
cin>>goods[i].w;
cout<<"请输入第"<
";
cin>>goods[i].p;
goods[i].p=goods[i].p/goods[i].w;//得出物品的效益,重量比
cout<}
Insertionsort(goods,n);
bag(goods,M,n);
cout<<"press<1>torunagian"<cout<<"press<0>toexit"<cin>>j;
}
}
结果截图:
(2)分支限界法:
#include
#include
#defineMaxSize100//最多结点数
typedefstructQNode
{
floatweight;
floatvalue;
intceng;
structQNode*parent;
boolleftChild;
}QNode,*qnode;//存放每个结点
typedefstruct
{
qnodeQ[MaxSize];
intfront,rear;
}SqQueue;//存放结点的队列
SqQueuesq;
floatbestv=0;//最优解
intn=0;//实际物品数
floatw[MaxSize];//物品的重量
floatv[MaxSize];//物品的价值
intbestx[MaxSize];//存放最优解
qnodebestE;
voidInitQueue(SqQueue&sq)//队列初始化
{
sq.front=1;
sq.rear=1;
}
boolQueueEmpty(SqQueuesq)//队列是否为空
{
if(sq.front==sq.rear)
returntrue;
else
returnfalse;
}
voidEnQueue(SqQueue&sq,qnodeb)//入队
{
if(sq.front==(sq.rear+1)%MaxSize)
{
printf("队列已满!
");
return;
}
sq.Q[sq.rear]=b;
sq.rear=(sq.rear+1)%MaxSize;
}
qnodeDeQueue(SqQueue&sq)//出队
{
qnodee;
if(sq.front==sq.rear)
{
printf("队列已空!
");
return0;
}
e=sq.Q[sq.front];
sq.front=(sq.front+1)%MaxSize;
returne;
}
voidEnQueue1(floatwt,floatvt,inti,QNode*parent,boolleftchild)
{
qnodeb;
if(i==n)//可行叶子结点
{
if(vt==bestv)
{
bestE=parent;
bestx[n]=(leftchild)?
1:
0;
}
return;
}
b=(qnode)malloc(sizeof(QNode));//非叶子结点
b->weight=wt;
b->value=vt;
b->ceng=i;
b->parent=parent;
b->leftChild=leftchild;
EnQueue(sq,b);
}
voidmaxLoading(floatw[],floatv[],intc)
{
floatwt=0;
floatvt=0;
inti=1;//当前的扩展结点所在的层
floatew=0;//扩展节点所相应的当前载重量
floatev=0;//扩展结点所相应的价值
qnodee=NULL;
qnodet=NULL;
InitQueue(sq);
EnQueue(sq,t);//空标志进队列
while(!
QueueEmpty(sq))
{
wt=ew+w[i];
vt=ev+v[i];
if(wt<=c)
{
if(vt>bestv)
bestv=vt;
EnQueue1(wt,vt,i,e,true);//左儿子结点进队列
}
EnQueue1(ew,ev,i,e,false);//右儿子总是可行;
e=DeQueue(sq);//取下一扩展结点
if(e==NULL)
{
if(QueueEmpty(sq))break;
EnQueue(sq,NULL);//同层结点尾部标志
e=DeQueue(sq);//取下一扩展结点
i++;
}
ew=e->weight;//更新当前扩展结点的值
ev=e->value;
}
printf("最优取法为:
\n");
for(intj=n-1;j>0;j--)//构造最优解
{
bestx[j]=(bestE->leftChild?
1:
0);
bestE=bestE->parent;
}
for(intk=1;k<=n;k++)
{
if(bestx[k]==1)
printf("\n物品%d:
重量:
%.1f,价值:
%.1f\n",k,w[k],v[k]);
}
printf("\n");
printf("最优价值为:
%.1f\n\n",bestv);
}
voidmain()
{
intc;
floatewv[MaxSize];
printf("////////////////////0-1背包问题分枝限界法/////////////////////\n\n");
printf("请输入物品的数量:
\n");
scanf("%d",&n);
printf("请输入背包的最大承重量:
\n");
scanf("%d",&c);
printf("\n请输入物品的重量和单位重量价值:
\n\n");
for(inti=1;i<=n;i++)
{
printf("物品%d:
",i);
scanf("%f%f",&w[i],&ewv[i]);
v[i]=w[i]*ewv[i];
printf("\n");
}
maxLoading(w,v,c);
}
结果截图: