1009040130贺程实验3.docx
- 文档编号:9633244
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:22
- 大小:105.60KB
1009040130贺程实验3.docx
《1009040130贺程实验3.docx》由会员分享,可在线阅读,更多相关《1009040130贺程实验3.docx(22页珍藏版)》请在冰豆网上搜索。
1009040130贺程实验3
《算法分析与设计》实验报告
实验三贪心方法算法设计
姓名贺程学号1009040130班级电子商务1002班
时间2013/3/26地点文波机房
同组人无
指导教师朱少林
实验目的与要求
a)掌握贪心法算法设计的一般思想和方法。
b)掌握背包问题、最小生成树、单源点最短路径算法设计。
c)掌握贪心法设计算法求解一般问题。
实验内容
d)背包问题的贪心法算法设计和程序验证。
e)最小生树算法设计和程序验证。
f)单源点最短路径算法设计和程序验证。
相关内容
(1)贪心方法的一般思想
ProcedureGREEDY(A,n)
//A(1:
n)包含n个输入//
Solution←Ф//将解向量初始化为空//
fori←1tondo
x←SELECT(A)
ifFEASIBLE(solution,x)
thensolution←UNION(solution,x)
endif
repeat
return(solution)
endGREEDY
(2)背包问题的贪心算法
ProcedureGREEDY-KNAPSACK(P,W,M,X,n)
//P(1:
n)和W(1:
n)分别含有按P(i)/W(i)≥P(i+1)/W(i+1)按序的n件物品的效益值和重量。
M是背包的容量大小,而X(1:
n)是解向量。
//
integeri,n;
realP(1:
n),W(1:
n),X(1:
n),M,cu;
X←0//将解向量初始化为零//
cu←M//cu是背包剩余容量//
fori←1tondo
ifW(i)>cuthenexitendif
X(i)←1
cu←cu-W(i)
repeat
ifi≤nthenX(i)←cu/W(i)endif
endGREEDY-KNAPSACK
(3)最小生成树问题的Prim算法
LineprocedurePRIM(E,COST,n,T,mincost)
//E是G的边集,COST(n,n)是一个正实数集合,如果不存在边(i,j),则为+∞。
计算一棵最小生成树并把它作为一个集合存放到数组T中,最小成本生成树的总成本最后赋给mincost。
//
1realCOST(n,n),mincost;
2integerNEAR(n),n,I,j,k,l,T(1:
n-1,2);
3(k,l)←具有最小成本的边
4mincost←COST(k,l)
5((T(1,1),T(1,2))←(k,l)
6fori←1tondo
7ifCOST(i,l) 8elseNEAR(j)←kendif 9repeat 10NEAR(k)←NEAR(l)←0 11fori←2ton-1do 12设j是NEAR(j)≠0且COST(j,NEAR(j))最小的下标 13((T(i,1),T(i,2))←(j,NEAR(j)) 14mincost←mincost+COST(j,NEAR(j)) 15NEAR(j)←0 16fork←1tondo 17ifNEAR(k)≠0andCOST(k,NEAR(k))>COST(k,j) 18thenNEAR(k)←j 19endif 20repeat 21repeat 22ifmincost≥∞thenprint(‘nospanningtree’)endif 23endPRIM (4)最小生成树问题的Kruskal算法 LineprocedureKRUSKAL(E,COST,n,T,mincost) //G有n个结点,E是G的边集,COST(u,v)是边(u,v)的成本。 T是最小成本生成树的边集,mincost是它的成本。 // 1realmincost,COST(1: n,1: n) 2integerPARENT(1: n),T(1: n-1,2),n 3以边成本为元素构造一个min-堆 4PARENT←-1 5i←mincost←0 6whilei 7从堆中删去最小成本边(u,v)并重新构造堆 8j←FIND(u);k←FIND(v) 9ifj≠ktheni←i+1 10T(i,1)←u;T(I,2)←v 11mincost←mincost+COST(u,v) 12callUNION(j,k) 13endif 14repeat 15ifi≠n-1thenprint(‘nospanningtree’)endif 16return 17endKRUSKAL (5)生成单源点最短路径的贪心算法(Dijkstra算法) LineprocedureSHORTEST-PATHs(v,COST,DIST,n) //G是一个n结点的有向图,它由其成本邻接矩阵COST(n,n)表示。 DIST(j)被置以从结点v到结点j的最短路径长度,这里1≤j≤n。 DIST(v)被置成零。 // BooleanS(1: n);realCOST(1: n,1: n),DIST(1: n) Integeru,v,n,num,I,w 1fori←1tondo 2S(i)←0;DIST(i)←COST(v,i) 3repeat 4S(v)←1;DIST(v)←0 5fornum←2ton-1do 6选取结点u,它使得DIST(u)=minS(w)=0{DIST(w)} 7S(u)←1 8for所有S(w)=0的结点wdo 9DIST(w)←min(DIST(w),DIST(u)+COST(u,w)) 10repeat 11repeat 12endSHORTEST-PATHS 实验步骤 g)准备实验数据。 对背包问题、最小生成树、最短路径问题按要求准备相应模拟数据,最好多准备几组。 h)背包问题的贪心法算法设计与验证。 i)最小生树算法设计与验证。 j)单源点最短路径算法设计与验证。 附加实验与思考 k)将教材中的作业排序算法转换成程序,用模拟数据运行,分析并比较算法效率。 l)修改最短路径算法,使得它在获得最短路径长度的同时还得到这些最短路径。 实验步骤 1、背包问题的贪心算法 定义物品结构体: typedefstructGoods{ floatp;//物品价值 floatw;//物品重量 intnum;//物品编号 floatx;//物品实际放入量 }; 用于存放各个物品的信息,取课本上的例子,3个物品,其编号1,2,3对应的重量和价值分别为(18,15,10)和(25,24,15),以及背包的体积,将其存放到文件knap.txt。 先调用sortPW(Goodsgoods[],intn)函数对文件中存放的物品按P(i)/W(i)≥P(i+1)/W(i+1)进行排序。 排好序后,在调用贪心函数greedy_knapsack(Goodsgoods[],intn,floatM,floatx[])进行求解,将求解结果保存到解向量*x中,并将最终去拼编号对应的装填物品的量写到文件result.txt中。 knap.txt: 20 3 12518 22415 31510 result.txt: : 21.00 30.50 10.00 以下是完整的程序代码: #include #include typedefstructGoods{ floatp;//物品价值 floatw;//物品重量 intnum;//物品编号 floatx;//物品实际放入量 }; voidsortPW(Goodsgoods[],intn){ inti,j; Goodstemp; for(i=0;i for(j=i+1;j if(goods[i].p/goods[i].w temp=goods[i]; goods[i]=goods[j]; goods[j]=temp; } } } } voidgreedy_knapsack(Goodsgoods[],intn,floatM,floatx[]){ inti; floatcu=M;//背包剩余体积 for(i=0;i x[i]=0; } for(i=0;i if(goods[i].w>cu) break; x[i]=1; cu-=goods[i].w; } if(i x[i]=cu/goods[i].w; } voidmain(){ intn,i;//n物品数量cu背包剩余体积 FILE*f1,*f2;//f1用于源文件,f2用于存放结果 Goods*g; float*x,M;//M背包体积*x为解向量 x=(float*)malloc(sizeof(float)); f1=fopen("knap.txt","r"); f2=fopen("result.txt","w"); fscanf(f1,"%f",&M);//背包体积M fscanf(f1,"%d",&n);//物品数量n g=(Goods*)malloc(n*sizeof(Goods));//为物品动态分配内存 for(i=0;i fscanf(f1,"%d",&g[i].num); fscanf(f1,"%f",&g[i].p); fscanf(f1,"%f",&g[i].w); } sortPW(g,n);//根据价值和重量的比非递增排序 greedy_knapsack(g,n,M,x);//贪心算法解背包问题 for(i=0;i fprintf(f2,"%d\t%.2f\n",g[i].num,x[i]); } fclose(f1); fclose(f2); } 运行结果在文件result.txt中得到: 21.00 30.50 10.00 2、最小生成树算法Prim 最小生成树Prim算法,文件prim.txt中存放的是节点数字1、数字2、数字3,分别表示: 节点1、节点2、权值。 prim.txt: 126 131 145 235 253 345 356 364 566 462 该算法对应解决的图: 以下是程序完整代码: #include #include #include #defineinfinity1000000 #definemax_vertexes6 typedefintGraph[max_vertexes][max_vertexes]; voidprim(GraphG,intvcount,intfather[]){ inti,j,k; intlowcost[max_vertexes]; intcloseset[max_vertexes],used[max_vertexes]; intmin; for(i=0;i /*最短距离初始化为其他节点到1号节点的距离*/ lowcost[i]=G[0][i]; /*标记所有节点的依附点皆为默认的1号节点*/ closeset[i]=0; used[i]=0; father[i]=-1; } used[0]=1;/*第一个节点是在s集合里的*/ /*vcount个节点至少需要vcount-1条边构成最小生成树*/ for(i=1;i<=vcount-1;i++){ j=0; min=infinity; /*找满足条件的最小权值边的节点k*/ for(k=1;k /*边权值较小且不在生成树中*/ if((! used[k])&&(lowcost[k] min=lowcost[k]; j=k; } father[j]=closeset[j]; printf("%d%d\n",j+1,closeset[j]+1);//打印边 used[j]=1;;//把第j个顶点并入了U中 for(k=1;k /*发现更小的权值*/ if(! used[k]&&(G[j][k] lowcost[k]=G[j][k];/*更新最小权值*/ closeset[k]=j;;/*记录新的依附点*/ } } } intmain(){ FILE*fr; inti,j,weight; GraphG; intfatheer[max_vertexes]; for(i=0;i for(j=0;j G[i][j]=infinity; fr=fopen("prim.txt","r"); if(! fr){ printf("fopenfailed\n"); exit (1); } while(fscanf(fr,"%d%d%d",&i,&j,&weight)! =EOF){ G[i-1][j-1]=weight; G[j-1][i-1]=weight; } prim(G,max_vertexes,fatheer); return0; } 程序运行结果为: 表示从尾节点编号到头结点编号的路径,构成的最小生成树。 3、最小生成树算法Kruskal 最小生成树算法Kruskal,文件kruskal.txt中第一行存放节点个数和边的个数 以后各行存放节点1编号,节点2编号,以及节点1到节点2的边的权值。 kruskal.txt: 610 126 131 145 235 253 345 356 364 566 462 对应的图为: 以下是程序完整代码: #include #include #include usingnamespacestd; constintmaxn=101;//图的最大节点数 structedge//边 { intfrom;//起点 intto;//终点 intcost;//路径长 friendbooloperator<(constedge&e1,constedge&e2) { returne1.cost>e2.cost; } }; FILE*f; edgeremMST[maxn];//记录组成最小生成树的边 intfather[maxn];//用来做并查集 intnodeNum,edgeNum;//顶点数、边数 intMST;//最小生成树 priority_queue voidstoreMap()//存储岛的桥构成的图 { while(! myQ.empty())myQ.pop();//清空 intfrom,to,cost; for(inti=0;i { fscanf(f,"%d%d%d",&from,&to,&cost); edgee; e.from=from; e.to=to; e.cost=cost; myQ.push(e); } } intfind(intx)//查找 { if(x==father[x])returnfather[x]; returnfather[x]=find(father[x]); } booljudge()//判断是否是一棵最小生成树,这里得注意起点和终点 { intf=find (1); for(inti=2;i<=nodeNum;i++) { if(f! =find(i)) { returnfalse; } } returntrue; } voidkruskal()//kruskal算法 { MST=0; for(inti=0;i { father[i]=i; } intnum=0;//记录MST的边数 while(! myQ.empty()&&num! =nodeNum-1) { edgee=myQ.top(); myQ.pop(); intfx=find(e.from); intfy=find(e.to); if(fx! =fy) { father[fx]=fy; MST+=e.cost; remMST[num].from=e.from; remMST[num].to=e.to; remMST[num].cost=e.cost; num++; } } } voidoutput()//打印最小生成树的值以及由哪些边组成 { if(judge()) { printf("fromtocost\n"); for(inti=0;i { printf("%d%d%d\n",remMST[i].from,remMST[i].to,remMST[i].cost); } printf("最小生成树的值是: %d\n",MST); } elseprintf("NoMSTExist! \n"); } intmain() { f=fopen("kruskal.txt","r"); if(! f){ printf("fopenfailed\n"); exit (1); } fscanf(f,"%d%d",&nodeNum,&edgeNum); storeMap(); kruskal(); output(); return0; } 程序运行结果,打印两个节点编号及对应的权值,并输出最小生成树的总代价。 4、生成单源点最短路径的贪心算法(Dijkstra算法) 单源点最短路径Dijkstra算法,文件dijkstra.txt中存放的内容分为三部分: 1,存放的是节点个数和路径个数,2存放的事点到点及其之间的权值,3存放的是源节点和终结点。 该算法求解对应的图为: 文件dijkstra.txt中的内容: 68 1310 1530 16100 235 3450 4610 5420 5660 16 其中6表示定点数,8表示弧数,该问题求解v0到v5,v0对应的事数字1,v1对应的是数字2,以此类推。 以下是完整的程序代码: #include #include #definemaxnodenum100 #definemaxedgenum100 #defineMAX_VALUE200 intmatrix[maxnodenum][maxnodenum]; intnodes[maxnodenum],dist[maxnodenum],prev[maxnodenum]; intnodenum,edgenum; FILE*f; voidmatrix_init(void); voiddijkstra(intv); voidprint_dijkstra(intv,inte); voidmain(intargc,char**argv){ intv,e; f=fopen("dijkstra.txt","r"); if(! f){ printf("fopenfailed\n"); exit (1); } matrix_init();//初始化顶点数、边数、点到点及其权值 fscanf(f,"%d",&v);//源点 dijkstra(v);//迪杰斯特拉算法 fscanf(f,"%d",&e);//终点 print_dijkstra(v,e);//打印结果 } voidmatrix_init(void){ inti,j,row,col,weight; fscanf(f,"%d%d",&nodenum,&edgenum);//边和顶点数 for(i=1;i<=nodenum;i++){ for(j=1;j<=nodenum;j++){ matrix[i][j]=MAX_VALUE; } } for(i=0;i fscanf(f,"%d%d%d",&row,&col,&weight); matrix[row][col]=weight; } } v
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 1009040130 实验