noip信息竞赛100个大体算法.docx

上传人:b****3 文档编号:1369153 上传时间:2022-10-21 格式:DOCX 页数:17 大小:19.36KB
下载 相关 举报
noip信息竞赛100个大体算法.docx_第1页
第1页 / 共17页
noip信息竞赛100个大体算法.docx_第2页
第2页 / 共17页
noip信息竞赛100个大体算法.docx_第3页
第3页 / 共17页
noip信息竞赛100个大体算法.docx_第4页
第4页 / 共17页
noip信息竞赛100个大体算法.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

noip信息竞赛100个大体算法.docx

《noip信息竞赛100个大体算法.docx》由会员分享,可在线阅读,更多相关《noip信息竞赛100个大体算法.docx(17页珍藏版)》请在冰豆网上搜索。

noip信息竞赛100个大体算法.docx

noip信息竞赛100个大体算法

noip信息竞赛100个大体算法

大体算法

     

     求两数的最大公约数

     functiongcd(a,b:

integer):

integer;

     begin

     ifb=0thengcd:

=a

     elsegcd:

=gcd(b,amodb);

     end;

     

     求两数的最小公倍数

     functionlcm(a,b:

integer):

integer;

     begin

     ifa

     lcm:

=a;

     whilelcmmodb>0doinc(lcm,a);

     end;

     

     素数的求法

     A.小范围内判定一个数是不是为质数:

     functionprime(n:

integer):

Boolean;

     varI:

integer;

     begin

     forI:

=2totrunc(sqrt(n))do

     ifnmodI=0thenbegin

     prime:

=false;exit;

     end;

     prime:

=true;

     end;

     

     B.判定longint范围内的数是不是为素数(包括求50000之内的素数表):

     proceduregetprime;

     var

     i,j:

longint;

     p:

array[1..50000]ofboolean;

     begin

     fillchar(p,sizeof(p),true);

     p[1]:

=false;

     i:

=2;

     whilei<50000dobegin

     ifp[i]thenbegin

     j:

=i*2;

     whilej<50000dobegin

     p[j]:

=false;

     inc(j,i);

     end;

     end;

     inc(i);

     end;

     l:

=0;

     fori:

=1to50000do

     ifp[i]thenbegin

     inc(l);pr[l]:

=i;

     end;

     end;{getprime}

     

     functionprime(x:

longint):

integer;

     vari:

integer;

     begin

     prime:

=false;

     fori:

=1toldo

     ifpr[i]>=xthenbreak

     elseifxmodpr[i]=0thenexit;

     prime:

=true;

     end;{prime}

     

     2.

     

     3.

     

     

     算法:

     procedureprim(v0:

integer);

     var

     lowcost,closest:

array[1..maxn]ofinteger;

     i,j,k,min:

integer;

     begin

     fori:

=1tondobegin

     lowcost[i]:

=cost[v0,i];

     closest[i]:

=v0;

     end;

     fori:

=1ton-1dobegin

     {寻觅离生成树最近的未加入极点k}

     min:

=maxlongint;

     forj:

=1tondo

     if(lowcost[j]0)thenbegin

     min:

=lowcost[j];

     k:

=j;

     end;

     lowcost[k]:

=0;{将极点k加入生成树}

     {生成树中增加一条新的边k到closest[k]}

     {修正各点的lowcost和closest值}

     forj:

=1tondo

     ifcost[k,j]

     lowcost[j]:

=cost[k,j];

     closest[j]:

=k;

     end;

     end;

     end;{prim}

     

     算法:

(贪婪)

     按权值递增顺序删去图中的边,假设不形成回路那么将此边加入最小生成树。

     functionfind(v:

integer):

integer;{返回极点v所在的集合}

     vari:

integer;

     begin

     i:

=1;

     while(i<=n)and(notvinvset[i])doinc(i);

     ifi<=nthenfind:

=ielsefind:

=0;

     end;

     

     procedurekruskal;

     var

     tot,i,j:

integer;

     begin

     fori:

=1tondovset[i]:

=[i];{初始化概念n个集合,第I个集合包括一个元素I}

     p:

=n-1;q:

=1;tot:

=0;{p为尚待加入的边数,q为边集指针}

     sort;

     {对所有边按权值递增排序,存于e[I]中,e[I].v1与e[I].v2为边I所连接的两个极点的序号,e[I].len为第I条边的长度}

     whilep>0dobegin

     i:

=find(e[q].v1);j:

=find(e[q].v2);

     ifi<>jthenbegin

     inc(tot,e[q].len);

     vset[i]:

=vset[i]+vset[j];vset[j]:

=[];

     dec(p);

     end;

     inc(q);

     end;

     writeln(tot);

     end;

     

     

     A.标号法求解单源点最短途径:

     var

     a:

array[1..maxn,1..maxn]ofinteger;

     b:

array[1..maxn]ofinteger;{b[i]指极点i到源点的最短途径}

     mark:

array[1..maxn]ofboolean;

     

     procedurebhf;

     var

     best,best_j:

integer;

     begin

     fillchar(mark,sizeof(mark),false);

     mark[1]:

=true;b[1]:

=0;{1为源点}

     repeat

     best:

=0;

     fori:

=1tondo

     Ifmark[i]then{对每一个已计算出最短途径的点}

     forj:

=1tondo

     if(notmark[j])and(a[i,j]>0)then

     if(best=0)or(b[i]+a[i,j]

     best:

=b[i]+a[i,j];best_j:

=j;

     end;

     ifbest>0thenbegin

     b[best_j]:

=best;mark[best_j]:

=true;

     end;

     untilbest=0;

     end;{bhf}

     

     算法求解所有极点对之间的最短途径:

     procedurefloyed;

     begin

     forI:

=1tondo

     forj:

=1tondo

     ifa[I,j]>0thenp[I,j]:

=Ielsep[I,j]:

=0;{p[I,j]表示I到j的最短途径上j的前驱结点}

     fork:

=1tondo{列举中间结点}

     fori:

=1tondo

     forj:

=1tondo

     ifa[i,k]+a[j,k]

     a[i,j]:

=a[i,k]+a[k,j];

     p[I,j]:

=p[k,j];

     end;

     end;

     

     C.Dijkstra算法:

     类似标号法,本质为贪婪算法。

     var

     a:

array[1..maxn,1..maxn]ofinteger;

     b,pre:

array[1..maxn]ofinteger;{pre[i]指最短途径上I的前驱结点}

     mark:

array[1..maxn]ofboolean;

     proceduredijkstra(v0:

integer);

     begin

     fillchar(mark,sizeof(mark),false);

     fori:

=1tondobegin

     d[i]:

=a[v0,i];

     ifd[i]<>0thenpre[i]:

=v0elsepre[i]:

=0;

     end;

     mark[v0]:

=true;

     repeat{每循环一次加入一个离1集合最近的结点并调整其他结点的参数}

     min:

=maxint;u:

=0;{u记录离1集合最近的结点}

     fori:

=1tondo

     if(notmark[i])and(d[i]

     u:

=i;min:

=d[i];

     end;

     ifu<>0thenbegin

     mark[u]:

=true;

     fori:

=1tondo

     if(notmark[i])and(a[u,i]+d[u]

     d[i]:

=a[u,i]+d[u];

     pre[i]:

=u;

     end;

     end;

     untilu=0;

     end;

    

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 韩语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1