算法实习报告Word文件下载.docx
《算法实习报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《算法实习报告Word文件下载.docx(13页珍藏版)》请在冰豆网上搜索。
StatusTopologicalSort(ALGraphG)
{
FindInDegree(G,indegree);
InitStack(S);
for(i=0;
i<
G.Vexnum;
++i)
if(!
indegree(i))
push(S,i);
count=0;
StachEmpty(s)){
pop(S,i);
printf(i,G.vertices(i),data);
count++;
for(p=G.vertices[i].firstarc;
p;
p=p->
nextarc){
k=p->
adjvex;
(--indegree(k)))
push(S,K);
}
if(count<
G.vexnum)
returnERROR;
else
returnOK;
迪杰斯拉特(Dijkstra)算法:
该算法提出了一个按路径递增的顺序产生最短路径的算法。
首先引入一个辅助向量D,它的分量D(i)表示当前所有找到的从始点V到每个终点Vi的最短路径的长度。
其初态为:
若从V到Vi有弧,则D(i)为弧上权,否则为无穷大;
显然,长度为
D(j)=Min{D(i)|ViV}
的路径是从V出发的最短一条路径,此路径为(V,Vj)。
网络的可靠性
时间限制:
3000ms|内存限制:
65535KB
难度:
3
描述
A公司是全球依靠的互联网解决方案提供商,也是2010年世博会的高级赞助商。
它将提供先进的网络协作技术,展示其”智能+互联“的生活概念,同时为参观者提供高品质的个人体验和互动,以”信息通信,尽情城市梦想”为主题贯穿。
借助奇幻的剧场大屏幕和特效,展现信息通信技术的应用前景,通过生动形象的故事,向观众展示沟通无限制的未来社会前景。
为此,A公司为世博园的N个区域建立了视频通信系统,其中每个区域建立一个基站,编号依次为1,2,3...,N。
通过基站之间的通信线路为各区域的参观者提供视频服务。
已知在各基站之间已铺设了一些光纤通讯线路,这些线路覆盖了所有的区域,即任意两个区域都可以进行视频传递。
但为了节约成本开支,目前只铺设了N-1条线路,同时为了减轻各基站的信息传递负载,每个基站最多有三条光纤通讯线路与之连接。
但在通信系统试运行期间,A公司发现当某个基站发生故障时,会导致其它区域之间无法进行信息传递。
为了提高该通信网络的可靠性,A公司准备在基站之间再新铺设一些光纤线路,使得任意一个基站故障后,其它基站之间仍然可以通讯。
由于铺设线路的成本昂贵,A公司希望新增设的光纤线路越少越好。
A公司请求Dr.Kong来完成这个任务
输入
有多组测试数据,以EOF为结束标志。
第一行:
N表示有N个基站
接下来有N-1行:
XY表示第X个基站与第Y个基站直连
1<
=N<
=10000
输出
输出一个整数,表示至少需新铺设的光纤线路数
样例输入
8
13
32
53
54
56
27
28
样例输出
#include<
cstdio>
#include<
iostream>
cstring>
usingnamespacestd;
#definemax10001
intresult[max];
intmain()
{
intn,i,a,b;
while(scanf("
%d"
&
n)!
=EOF)
{
memset(result,0,sizeof(result));
n-1;
i++)
scanf("
%d%d"
a,&
b);
result[a]++;
result[b]++;
}
intsum=0;
=n;
if(result[i]==1)
sum++;
printf("
%d\n"
sum%2==0?
sum/2:
(sum/2+1));
return0;
}
回溯法:
实际上是一种搜索问题的解的一种方法。
所采用的方法一般为深度优先搜索法,所搜索的路径一般是沿树形结构进行搜索。
在搜索过程中,首先会判断所搜索的树结点是否包含问题的解,如果肯定不包含,则不再搜索以该结点为根的树结点,而向其祖先结点回溯。
否则进入该子树,继续按深度优先策略搜索。
1)递归回溯
利用递归算法对树进行深度遍历,并在遍历过程中不断地判断当前搜索的结点是否符合搜索条件,如果符合继续进行深度遍历,否则剪去该分支,搜索后续分支。
2)迭代回溯
采用树的非递归深度优先遍历方法也可实现回溯算法。
非递归算法实际上是用循环来取代递归进行回溯。
装载问题
有一批共n个集装箱要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量为wi,且∑wi<
=C1+C2,其中1<
=i<
=n。
问是否可以找到一种装载方法是的这n个集装箱可以装载到这2艘轮船上。
装载问题是一个NP问题。
在该问题中,可以采用下面的策略:
(1)首先尽可能的将第一艘轮船装满。
(2)看剩余的货物能否装入第2艘船。
为什么可采用上述策略呢?
可以证明!
显然,对于策略
(1)需要去搜索一些货物,使其货物重量尽可能的接近于第一艘轮船的装载量。
这个搜索策略当然可采用回溯法实现。
//ModifyMaxLoading.cpp:
定义控制台应用程序的入口点。
//
#include"
stdafx.h"
template<
classType>
TypeMaxLoading(Typew[],Typec,intn);
classLoading{
friendTypeMaxLoading(Type[],Type,int);
public:
voidBacktrack(inti);
intn;
//集装箱数量
//w-->
集装箱重量数组;
c-->
第一艘轮船的载重量;
cw-->
当前载重量;
bestw-->
当前最优载重量
Type*w,c,cw,bestw;
//剩余集装箱重量
Typer;
};
intmain()
{
int*w,c,n,bestw,tc,Maxw=0;
//输入必要的数据
cout<
<
"
PleaseinputthenumberofContainer:
;
cin>
>
n;
w=newint[n];
Pleaseinputtheweightofeachcontainer:
for(inti=1;
i++){
cin>
w[i];
Maxw+=w[i];
PleaseinputtheMaximumweightforthefirstship:
c;
PleaseinputtheMaximumweightforthesecondship:
tc;
//调用函数实现回溯法搜索是否可以以最大限度的形式装载集装箱到第一艘船
bestw=MaxLoading(w,c,n);
//判断第2艘船是否可以装载下剩余的集装箱
if(Maxw-bestw<
tc)
cout<
thetwoshipcanloadallthecontainer:
endl;
else
thetwoshipcann'
tloadallthecontainer"
}
voidLoading<
Type>
:
Backtrack(inti)
//如果已到叶子结点
if(i>
n){
if(cw>
bestw)bestw=cw;
return;
//搜索子树,减去第i个集装箱的重量为剩余集装箱重量
r-=w[i];
//访问左子树
if(cw+w[i]<
=c){
cw+=w[i];
Backtrack(i+1);
cw-=w[i];
//如果当前已装载货物的重量+剩余集装箱货物的重量>
当前已求的的最优解,则访问右子树
if(cw+r>
bestw)
Backtrack(i+1);
//因为是访问右子树,因此第i个集装箱并不装载到轮船上
r+=w[i];
TypeMaxLoading(Typew[],Typec,intn)
Loading<
X;
X.w=w;
X.c=c;
X.n=n;
X.bestw=0;
X.cw=0;
//求解剩余集装箱的重量
X.r=0;
i++)
X.r+=w[i];
X.Backtrack
(1);
returnX.bestw;
上述算法只求的了最优解,但具体是元素构成了最优解呢并不知道。
因此可通过增加两个成员变量的方法来记录求解出的最优解。
一个是x,另一个是bestx。
X用于记录从根到当前结点的路径,bestx记录当前最优解。
//XModifyMaxLoading.cpp:
TypeMaxLoading(Typew[],Typec,intn,intbestx[]);
friendTypeMaxLoading(Type[],Type,int,int[]);
//x-->
当前解bestx-->
当前最优解
int*x,*bestx;
int*w,c,n,bestw,tc,Maxw=0,*bestx;
w=newint[n+1];
bestx=newint[n+1];
bestw=MaxLoading(w,c,n,bestx);
bestw){
//如果当前解是目前所找到的最优解,将当前解作为最优解保存到bestx中
for(intj=1;
j<
j++)
bestx[j]=x[j];
bestw=cw;
}
//用1表示第i个结点是被选中的结点
x[i]=1;
//该结点未被选中
x[i]=0;
//因为是访问右子树,因此第i个集装箱并不装载到轮船上
TypeMaxLoading(Typew[],Typec,intn,intbestx[])
X.bestx=bestx;
//分配n+1个空间用于存储每个集装箱是否被选中的标志
X.x=newint[n+1];
delete[]X.x;
感想:
在这短暂而又漫长的二十天实习中,我们在相同的兴趣下一起训练,一起A题,一起学习,在这当中我们学到了很多,也提高了很多。
在实习过程中,我认识了许多以前很少听说和接触的算法,虽然还不是很深透的理解,但是在不断地钻研和请教中编程能力的确有了很大的提高。
在编程的时候,面对每个问题都需要自己想出合适的思路和算法,在无数次的wronganswer后看到令你欣喜若狂的accepted,那种心情简直兴奋的无法形容。
同时以小组的形式做题更增强了我的团队合作能力和组织能力,团队合作总是比孤军奋战强。
看到同伴的努力自己自然而然地积极起来,看到同伴提交的题目通过后自然增强了团队的自信心。
通过团队合作获得的胜利喜悦之情无疑是这个夏日里最凉爽的清泉。
在这里,我也要感谢各位一起集训的ACM校队的大神们给我们仔细地讲解题目,在QQ群里不断更新,很多都是有用的信息。
这次实习是人生中一大宝贵财富。