河北工业大学算法分析与设计实验报告Word下载.docx
《河北工业大学算法分析与设计实验报告Word下载.docx》由会员分享,可在线阅读,更多相关《河北工业大学算法分析与设计实验报告Word下载.docx(15页珍藏版)》请在冰豆网上搜索。
inti,j,t,temp;
a[1][1]=1;
a[1][2]=2;
a[2][1]=2;
a[2][2]=1;
for(t=1;
t<
k;
t++)
{
temp=n;
n=n*2;
for(i=temp+1;
i<
=n;
i++)
for(j=1;
j<
=temp;
j++)
a[i][j]=a[i-temp][j]+temp;
for(i=1;
for(j=temp+1;
a[i][j]=a[i+temp][j-temp];
i<
a[i][j]=a[i-temp][j-temp];
}
}
intmain()
inti,j,k;
inta[80][80];
printf("
请输入k的数值k="
);
scanf("
%d"
&
k);
GameTable(k,a);
for(i=1;
=pow(2,k);
for(j=1;
printf("
%5d"
a[i][j]);
printf("
\n"
return0;
【运行结果】
【分析总结】
本次实验思路简单,并且编程实现也不复杂。
通过这次试验,我对于分治法的设计思想理解地更加深入。
其主要思想就是将一个大问题,分解为一个个的小问题,知道每个小问题很容易求出解为止。
最后再将子问题的解合并为一个更大规模的问题的解,自底向上逐步求出元问题的解。
实验二
(1)熟练掌握动态规划思想及教材中相关经典算法。
(2)掌握动态规划算法求解问题的一般特征和步骤;
使用动态规划法编
程,求解0/1背包问题。
0/1背包问题是给定n个重量为{w1,w2,…,wn}、价值为{v1,v2,…,vn}的物品和一个容量为C的背包,求这些物品中的一个最有价值的子集,并且要能够装到背包中。
在0/1背包问题中,物品i或者被装入背包,或者不被装入背包,设xi表示物品i装入背包的情况,则当xi=0时,表示物品i没有被装入背包,xi=1时,表示物品i被装入背包。
0/1背包问题可以看作是决策一个序列(x1,x2,…,xn),对任一变量xi的决策是决定xi=1还是xi=0。
在对xi-1决策后,已确定了(x1,…,xi-1),在决策xi时,问题处于下列两种状态之一:
(1)背包容量不足以装入物品i,则xi=0,背包不增加价值;
(2)背包容量可以装入物品i,则xi=1,背包的价值增加了vi。
这两种情况下背包价值的最大者应该是对xi决策后的背包价值。
//本程序的测试用例是课本上的例题
#include<
intx[100],V[100][100];
intmax(inta,intb)
return(a>
b?
a:
b);
intKnapSack(intw[],intv[],intn,intC)
inti,j;
//初始化第0列
for(i=0;
V[i][0]=0;
//初始化第0行
for(j=0;
=C;
V[0][j]=0;
//双重for循环完成填表过程
for(j=1;
=C;
if(j<
w[i])V[i][j]=V[i-1][j];
elseV[i][j]=max(V[i-1][j],V[i-1][j-w[i]]+v[i]);
//从右下角开始往回寻找
for(j=C,i=n;
i>
0;
i--)
if(V[i][j]>
V[i-1][j])
x[i]=1;
j-=w[i];
elsex[i]=0;
//返回背包最大价值
returnV[n][C];
//n是物品个数;
C是背包总容量
intw[100],v[100],n,C;
请输入物品种类:
"
n);
请输入背包重量:
C);
请输入重量矩阵:
for(inti=1;
w[i]);
//这里注意i从1开始取值
请输入价值矩阵:
v[i]);
背包取得的最大价值为:
%d\n"
KnapSack(w,v,n,C));
问题的最优解序列为:
%2d"
x[i]);
\n\n"
二维矩阵V为:
for(inti=0;
for(intj=0;
%3d"
V[i][j]);
通过这次试验,我体会到了动态规划法设计思想的巧妙之处。
动态规划算法通常用于求解具有某种最优性质的问题。
在这类问题中,可能会有许多可行解。
每一个解都对应于一个值,都希望找到具有最优值的解。
动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。
实验三
6学时
掌握贪心算法求解问题的一般特征和步骤;
通过使用贪心算法求解0/1背包和TSP问题,进一步加深对贪心算法的理解和运用。
0/1背包问题是给定n个重量为{w1,w2,…,wn}、价值为{v1,v2,…,vn}的物品和一个容量为C的背包,求这些物品中的一个最有价值的子集,并且要能够装到背包中每次从物品集合中选择单位重量价值最大的物品,如果其重量小于背包容量,就可以把它装入,并将背包容量减去该物品的重量。
因此背包问题具有最优子结构性质。
TSP问题是指旅行家要旅行n个城市然后回到出发城市,要求各个城市经历且仅经历一次,并要求所走的路程最短。
1)最近邻点策略:
从任意城市出发,每次在没有到过的城市中选择最近的一个,直到经过了所有的城市,最后回到出发城市。
2)最短链接策略:
每次在整个图的范围内选择最短边加入到解集合中,但是,要保证加入解集合中的边最终形成一个哈密顿回路。
【0/1背包源程序】
//本程序的测试用例来源于课本例题
algorithm>
usingnamespacestd;
structG
doublev;
doublew;
doublex=0;
intflag=0;
}good[100];
boolcmp1(Ga,Gb)//按照性价比降序排序
returna.v/a.w>
b.v/b.w;
boolcmp2(Ga,Gb)//按照序号升序排序
returna.flag<
b.flag;
inti,n,C;
doublemaxValue=0;
n;
%lf"
good[i].w);
good[i].flag=i;
good[i].v);
sort(good,good+n,cmp1);
good[i].w<
good[i].x=1;
maxValue+=good[i].v;
C-=good[i].w;
good[i].x=(double)C/good[i].w;
maxValue+=good[i].x*good[i].v;
背包的最大价值为:
%.2f\n"
maxValue);
sort(good,good+n,cmp2);
问题的最优解向量为:
%.1f"
good[i].x);
【TSP源程序】
//#defineLOCAL
intarc[10][10];
intn;
//城市个数
intw;
//起点城市
intTSP(intn,intw)
intedgeCount=0,TSPLength=0;
intmin=100,u,v;
intflag[10]={0};
//可以对于flag数组中所有元素清零;
u=w;
flag[w]=1;
while(edgeCount<
n-1)
min=100;
for(intj=1;
if(flag[j]==0&
&
arc[u][j]<
min)
v=j;
min=arc[u][j];
TSPLength+=arc[u][v];
flag[v]=1;
edgeCount++;
%d-->
u);
u=v;
v,w);
return(TSPLength+arc[u][w]);
#ifdefLOCAL
freopen("
data.in"
"
r"
stdin);
data.out"
w"
stdout);
#endif//LOCAL
请输入城市个数:
请输入代价矩阵:
arc[i][j]);
请输入起点城市:
w);
最短路径为:
最小代价为:
TSP(n,w));
通过这次试验,我更好地掌握了贪心法的设计思想。
运用贪心法时,主要有以下步骤:
1.建立数学模型来描述问题
2.把求解的问题分成若干个子问题。
3.对每一子问题求解,得到子问题的局部最优解。
4.把子问题的解局部最优解合成原来解问题的一个解。
实现该算法的过程:
从问题的某一初始解出发;
while能朝给定总目标前进一步
do
求出可行解的一个解元素;
由所有解元素组合成问题的一个可行解。
实验四
掌握回溯法的设计思想;
掌握解空间树的构造方法,以及在求解过程中如何存储求解路径;
考察回溯法求解问题的有效程度。
给定n种物品和一背包。
物品i的重量是wi>
0,其价值为vi>
0,背包的容量为c。
问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大?
TSP问题是指旅行家要旅行n个城市然后回到出发城市,要求各个城市经历且仅经历一次,并要求所走的路程最短。
iostream>
intn,c,bestp;
//物品的个数,背包的容量,最大价值
intp[100],w[100],x[100],bestx[100];
//物品的价值,物品的重量,x[i]暂存物品的选中情况,物品的选中情况
voidBacktrack(inti,intcp,intcw)
//cw当前包内物品重量,cp当前包内物品价值
intj;
if(i>
n)
//结束回溯
if(cp>
bestp)
bestp=cp;
i++)
bestx[i]=x[i];
else
j<
=1;
j++)
x[i]=j;
if(cw+x[i]*w[i]<
=c)
cw+=w[i]*x[i];
//每个解向量的分量的c与当前的w[i]和前一个解向量分量的cw有关
cp+=p[i]*x[i];
Backtrack(i+1,cp,cw);
//递归调用
cout<
<
endl;
inti;
bestp=0;
输入物品个数:
cin>
>
输入背包最大容量:
c;
依次输入物品的重量:
cin>
w[i];
请依次输入物品的价值:
p[i];
Backtrack(1,0,0);
最大价值为:
endl<
bestp<
物品的选中情况依次为(0表示没有被选中,1表示被选中)"
cout<
bestx[i];
1、重温了算法课程里面学过的回溯法,强化了这种编程思想。
2、深刻理解了递归调用的思想。
3、通过这次实验对回溯算法有了进一步的了解,把理论知识应用于实验中。
4、回溯算法的主要思想:
在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。
当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。
(其实回溯法就是对隐式图的深度优先搜索算法)。
若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。
而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。