﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-franlk-文章分类-算法</title><link>http://www.blogjava.net/franlk/category/11465.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 06:24:02 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 06:24:02 GMT</pubDate><ttl>60</ttl><item><title>[转帖]十类算法的详细说明</title><link>http://www.blogjava.net/franlk/articles/47795.html</link><dc:creator>FRANLK 的个人空间</dc:creator><author>FRANLK 的个人空间</author><pubDate>Wed, 24 May 2006 05:18:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/47795.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/47795.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/47795.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/47795.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/47795.html</trackback:ping><description><![CDATA[十类算法的详细说明 <br />偶以赛题为背景来说明一下： <br />1、蒙特卡罗算法： <br />在大多数建模赛题中都离不开计算机的仿真，随机性模拟是非常常见的算法之一。 <br />举个例子就是97年的A题，每个零件都有自己的标定值，也都有自己的容差等级，而求解最优的组合方案将要面对着的是一个极其复杂的公式和108种容差选取方案，根本不可能去解析求解的，那如何去找到最优的方案呢？随机性模拟搜索最优方案就是其中的一种方法，在每个零件可行的区间中按照正态分布随机的选取一个标定值和选取一个容差值作为一种方案，然后通过蒙特卡罗算法仿真出大量的方案，从中选取一个最佳的。另一个例子就是去年的彩票第二问，要求设计一种更好的方案，首先方案的优劣决定于很多复杂的因素，同样不可能刻画出一个模型进行求解，只能靠随机仿真模拟。 <br />2、数据拟合、参数估计、插值等算法： <br />数据拟合在很多赛题中有应用，与图形处理有关的问题很多与拟合有关系，一个例子就是98年美赛A题，生物组织切片的三维插值处理，94年A题逢山开路，山体海拔高度的插值计算，还有吵的沸沸扬扬可能会考的非典问题也要用到数据拟合算法，观察数据的走向进行处理。此类问题在Matlab中有很多数据处理现成的函数可以调用，熟悉Matlab，这些方法都能游刃有余的做好。 <br />3、规划类问题算法： <br />竞赛中很多问题都和数学规划有关，可以说不少的模型都可以归结为一组不等式组作为约束条件、几个函数表达式作为目标函数的问题，遇到这类问题，求解就是关键了，比如98B，用很多不等式完全可以把问题刻画清楚，因此列举出规划后用Lindo、Lingo等软件来进行解决比较方便，所以还需要熟悉这两个软件。 <br />4、图论问题： <br />98B、00B、95锁具装箱等问题体现了图论问题的重要性，这类问题算法有很多，包括：Dijkstra、Floyd、Prim、Bellman-Ford，最大流，二分匹配等问题。每一个算法认真的话都应该写一遍，否则到比赛时再写就晚了， <br />5、计算机算法设计中的问题： <br />计算机算法设计包括很多内容：动态规划、回溯搜索、分治算法、分支定界。比如92B用分支定界法，97B是典型的动态规划问题，此外98B体现了分治算法。这方面问题和acm中的问题类似，推荐的书籍有《计算机算法设计与分析》电子工业出版社等与计算机算法有关的书。 <br />6、最优化理论的三大非经典算法： <br />模拟退火法、神经网络、遗传算法。这十几年来最优化理论有了飞速发展，这三类算法发展很快，近几年的赛题越来越复杂，很多问题没有什么很好的模型可以借鉴，于是这三类算法很多时候可以派上用场，比如：97A的模拟退火算法、00B的神经网络分类算法、象01B这种难题也可以使用神经网络、还有美国竞赛89A也和BP算法有关系，当时是86年刚提出BP算法，89年就考了，说明赛题可能是当今前沿科技的抽象体现。03B伽马刀问题也是目前研究的课题，目前算法最佳的是遗传算法。 <br />7、网格算法和穷举算法 <br />网格算法和穷举法一样，只是网格法是连续问题的穷举。比如要求在N个变量情况下的最优化问题，那么可以对这些变量可取的空间进行采点，比如在[a,b]区间内取M+1个点，就是在a、a+(b-a)/M、a+2*(b-a)/M、……、b那么这样循环就需要进行(M+1)^N次运算，所以计算量很大。 <br />比如97年A题、99年B题都可以用网格法搜索，这种方法最好在运算速度叫快的计算机中进行，还有要用高级语言来做，最好不要用Matlab做网格，否则会算很久的。穷举法大家都熟悉，就不说了。 <br />8、一些连续离散化方法 <br />大部分物理问题的编程解决，都和这种方法有一定的联系，物理问题是反映我们生活在一个连续的世界中，计算机求解只认离散的变量，所以需要将连续量进行离散处理，这种方法应用很广，大都和上面的很多算法有关，事实上，网格算法、蒙特卡罗算法、模拟退火都用了这个思想。 <br />9、数值分析算法 <br />这类算法是针对高级语言而专门设的，如果你用的是Matlab、Mathematica，大可不必准备，因为象数值分析中有很多函数一般的数学工具是具备的。 <br />10、图象处理算法 <br />01A中需要你会读bmp图象、98美赛A需要你知道三维插值计算，03B要求更高，不但需要编程计算还要进行处理，而数模论文中也有很多图片需要展示，因此图象处理就是关键，做好这类问题，重要的是把Matlab学好，特别是图象处理的部分。 <br /><br />模拟退火算法（转载） <br /><br />退火概念是80年代初期研究组合优化问题时提出的，该方法解决优化问题 <br />的出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似 <br />性。在对固体物质进行退火处理时，通常是先将它加温熔化，使其中的粒子 <br />可以自由运动，然后降温，粒子就逐渐形成低能态的晶体。如果凝结点附近 <br />温度下降足够慢，那么固体物质一定能够形成最低能量的状态。模拟退火就 <br />是模拟了这一过程，从而求得组合优化问题的全局（近似）最优解。 <br /><br />------------------------------------------------- <br />发信人: daniel (小丹尼), 信区: AI <br />标 题: 模拟退火(2) <br />发信站: 南大小百合信息交换站 (Sun Apr 5 20:03:55 1998), 转信 <br /><br />设E[{xi}]表示某系统在微观状态{xi}（{xi}为一组状态变量，如速度、 <br />位置等）下的内能，对于给定温度T，如果系统处于热平衡状态，那么 <br />E[{xi}]将服从Boltzmann分布，分布函数为： <br /><br />f = C(T)e^(-E[{xi}]/kT) <br />C(T)-1/(e^(-E[{x1}]/kT)+e^(-E[{x2}]/kT)+...+e^(-E[{xn}]/kT)) <br /><br />其中k是Boltzmann常数。 <br /><br />T下降将导致内能E下降，如果T下降速度足够慢，那么系统就可以保持热 <br />平衡，使其内能在该温度下达到最低值。当T=0（开氏温度）时，内能将达到 <br />最小值。这样的降温过程就是退火过程。 <br /><br />------------------------------------------------- <br /><br />发信人: daniel (小丹尼), 信区: AI <br />标 题: 模拟退火(3) <br />发信站: 南大小百合信息交换站 (Sun Apr 5 20:04:45 1998), 转信 <br /><br />在退火过程中经常要用Metropolis抽样，它可以用来模拟温度T下系统的 <br />热平衡。 <br /><br />随机选一初始状态{xi}， 然后随机地给系统加一个扰动{delta xi},则 <br />内能增量为： <br /><br />delta E = E[{xi+delta xi}] - E[{xi}] <br /><br />如果delta E&lt;0，那么这个扰动就将被接受，否则该扰动将按概率 <br />e^(-delta E/kT) 被接受。如果扰动被接受，那么就用{xi+delta xi}代替 <br />原来的{xi}；否则就产生一个新的扰动...... <br /><br />如此反复，则{xi}将逐渐满足前述Boltzmann分布。 <br /><br />如果让T从一个足够大的值逐渐下降，对于每个T都用Metropolis抽样使 <br />系统热平衡，那么到T=0时，就实现了模拟退火，E[{xi}]达到最小值。 <br /><br />------------------------------------------------- <br />发信人: daniel (小丹尼), 信区: AI <br />标 题: 模拟退火(4) <br />发信站: 南大小百合信息交换站 (Sun Apr 5 20:05:19 1998), 转信 <br /><br />计算机实现模拟退火的思想是：将每种可能的组合状态作为{xi}，E作为 <br />目标函数，T作为控制参数，令T逐渐减小为0，从而得到目标函数最优值。 <br /><br />基本步骤为： <br /><br />初始化：对初始状态{xi}，取初始值T(0)，计算目标函数E[{xi}]； <br />1. 产生随机扰动，计算delta E = E[{xi+delta xi}] - E[{xi}] <br />2. 若delta E&lt;0, goto 4,否则产生[0，1]上的一个均匀分布随机数y； <br />3. 若e^(-E/T)&lt;=y，goto 1 ； <br />4. 用{xi+delta xi}代替{xi},E+delta E代替E; <br />5. 检验Metropolis抽样是否稳定，若不稳定，goto 1; <br />6. T减小； <br />7. 是否满足目标，是则结束，否则goto 1。 <br /><br />------------------------------------------------- <br /><br />发信人: daniel (小丹尼), 信区: AI <br />标 题: 模拟退火(5) <br />发信站: 南大小百合信息交换站 (Sun Apr 5 20:05:41 1998), 转信 <br /><br />模拟退火是否能达到E的最小值决定于T(0)是否足够大，和T是否下降得 <br />足够慢，以及对于每个T，Metropolis抽样是否稳定。 <br /><br />模拟退火的典型特征是除了接受目标函数的改进外，还接受一个衰减极限， <br />当T较大时，接受较大的衰减，当T逐渐减小时，接受较小的衰减，当T为0 <br />时，就不再接受衰减。这一特征意味着模拟退火与局部搜索相反，它能避开 <br />局部极小，并且还保持了局部搜索的通用性和简单性。 <br /><br />值得注意的是，当T为0时，模拟退火就成为局部搜索的一个特例<img src ="http://www.blogjava.net/franlk/aggbug/47795.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">FRANLK 的个人空间</a> 2006-05-24 13:18 <a href="http://www.blogjava.net/franlk/articles/47795.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]一些基本算法2</title><link>http://www.blogjava.net/franlk/articles/47794.html</link><dc:creator>FRANLK 的个人空间</dc:creator><author>FRANLK 的个人空间</author><pubDate>Wed, 24 May 2006 05:15:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/47794.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/47794.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/47794.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/47794.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/47794.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://vib.hit.edu.cn/vibbbs/dispbbs.asp?boardID=25&amp;ID=2357&amp;page=8">http://vib.hit.edu.cn/vibbbs/dispbbs.asp?boardID=25&amp;ID=2357&amp;page=8</a><br /><p>9.树的遍历顺序转换   </p><p>A. 已知前序中序求后序   <br />procedure Solve(pre,mid:string);   <br />var i:integer;   <br />begin   <br />    if (pre='') or (mid='') then exit;   <br />    i:=pos(pre[1],mid);   <br />    solve(copy(pre,2,i),copy(mid,1,i-1));   <br />    solve(copy(pre,i+1,length(pre)-i),copy(mid,i+1,length(mid)-i));   <br />    post:=post+pre[1]; {加上根，递归结束后post即为后序遍历}   <br />end;     </p><p>B.已知中序后序求前序   <br />procedure Solve(mid,post:string);   <br />var i:integer;   <br />begin   <br />    if (mid='') or (post='') then exit;   <br />    i:=pos(post[length(post)],mid);   <br />    pre:=pre+post[length(post)]; {加上根，递归结束后pre即为前序遍历}   <br />    solve(copy(mid,1,I-1),copy(post,1,I-1));   <br />    solve(copy(mid,I+1,length(mid)-I),copy(post,I,length(post)-i));   <br />end;     </p><p>C.已知前序后序求中序     <br />function ok(s1,s2:string):boolean;   <br />var i,l:integer; <br />    p:boolean;   <br />begin   <br />    ok:=true;   <br />    l:=length(s1);   <br />    for i:=1 to l do   <br />    begin   <br />        p:=false;   <br />        for j:=1 to l do   <br />        if s1[i]=s2[j] then p:=true;   <br />          if not p then   <br />          begin   <br />             ok:=false;exit;  <br />          end;   <br />        end;   <br />    end;     </p><p>procedure solve(pre,post:string);   <br />var i:integer;   <br />begin   <br />    if (pre='') or (post='') then exit;   <br />    i:=0;   <br />    repeat   <br />       inc(i);   <br />    until ok(copy(pre,2,i),copy(post,1,i));   <br />    solve(copy(pre,2,i),copy(post,1,i));   <br />    midstr:=midstr+pre[1];   <br />    solve(copy(pre,i+2,length(pre)-i-1),copy(post,i+1,length(post)-i-1));   <br />end;     </p><p>10.求图的弱连通子图(DFS)   <br />procedure dfs ( now,color: integer);   <br />begin   <br />    for i:=1 to n do   <br />        if a[now,i] and c[i]=0 then   <br />        begin   <br />           c[i]:=color;   <br />           dfs(I,color);   <br />        end;   <br />end;     </p><p>12.进制转换   <br />A.整数任意正整数进制间的互化     <br />NOIP1996数制转换   <br />设字符串A$的结构为: A$='mp'   <br />其中m为数字串(长度&amp;lt; =20),而n,p均为1或2位的数字串(其中所表达的内容在2-10之间) <br />程序要求:从键盘上读入A$后(不用正确性检查),将A$中的数字串m(n进制)以p进制的形式输出. <br />例如:A$='48&amp;lt; 10 &amp;gt;8'   其意义为:将10进制数48,转换为8进制数输出.   <br />输出结果:48&amp;lt; 10 &amp;gt;=60&amp;lt; 8 &amp;gt;     <br />B.实数任意正整数进制间的互化   <br />C.负数进制：   NOIP2000   设计一个程序，读入一个十进制数的基数和一个负进制数的基数，<br />并将此十进制数转换为此负 进制下的数：-R∈{-2，-3，-4,....-20}             </p><p>13.全排列与组合的生成   排列的生成：（1..n）   <br />procedure solve(dep:integer);   <br />var   i:integer;   <br />begin   <br />      if dep=n+1 then <br />      begin <br />         writeln(s);<br />         exit; <br />      end;   <br />      for i:=1 to n do   <br />         if not used[i] then   <br />         begin   <br />            s:=s+chr(i+ord('0'));<br />            used[i]:=true;   <br />            solve(dep+1);   <br />            s:=copy(s,1,length(s)-1); <br />            used[i]:=false;   <br />         end;   <br />end;   </p><p>组合的生成(1..n中选取k个数的所有方案)   <br />procedure solve(dep,pre:integer);   <br />var   i:integer;   <br />begin   <br />      if dep=k+1 then <br />      begin <br />         writeln(s);<br />         exit; <br />      end;   <br />      for i:=1 to n do   <br />         if (not used[i]) and (i &amp;gt;pre) then   <br />         begin   <br />             s:=s+chr(i+ord('0'));<br />             used[i]:=true;   <br />             solve(dep+1,i);   <br />             s:=copy(s,1,length(s)-1); <br />             used[i]:=false;   <br />         end;   <br />end;         <br /></p><p>14 递推关系   计算字串序号模型   USACO1.2.5 StringSobits   <br />长度为N (N&amp;lt; =31)的01串中1的个数小于等于L的串组成的集合中找出按大小排序后的第I个01串。<br />数字划分模型 <br />*NOIP2001数的划分 <br />将整数n分成k份，且每份不能为空，<br />任意两种分法不能相同(不考虑顺序)。 <br />d[0,0]:=1; <br />for p:=1 to n do <br />    for i:=p to n do <br />       for j:=k downto 1 do inc(d[i,j],d[i-p,j-1]); <br />           writeln(d[n,k]); <br />*变形1：考虑顺序 <br />d[ i, j] : = d [ i-k, j-1] (k=1..i) <br />*变形2：若分解出来的每个数均有一个上限m <br />d[ i, j] : = d [ i-k, j-1] (k=1..m) </p><p>15.算符优先法求解表达式求值问题 <br />const maxn=50; <br />var s1:array[1..maxn] of integer; {s1为数字栈} <br />    s2:array[1..maxn] of char; {s2为算符栈} <br />    t1,t2:integer; {栈顶指针} <br />procedure calcu; <br />var x1,x2,x:integer; <br />    p:char;<br />begin   <br />    p:=s2[t2]; <br />    dec(t2);   <br />    x2:=s1[t1]; <br />    dec(t1);   <br />    x1:=s1[t1]; <br />    dec(t1);   <br />    case p of   <br />      '+':x:=x1+x2;   <br />      '-':x:=x1-x2;   <br />      '*':x:=x1*x2;   <br />      '/':x:=x1 div 2;   <br />    end;   <br />    inc(t1);<br />    s1[t1]:=x; <br />end; <br />procedure work; <br />var c:char;<br />    v:integer; <br />begin   <br />    t1:=0;<br />    t2:=0;   <br />    read(c);   <br />    while c&amp;lt; &amp;gt;';' do   <br />       case c of  <br />       '+','-':   <br />       begin   <br />           while (t2 &amp;gt;0) and (s2[t2]&amp;lt; &amp;gt;'(') do calcu;   <br />               inc(t2);s2[t2]:=c;   <br />               read(c);   <br />       end ;   <br />       '*','/':  <br />       begin   <br />           if (t2 &amp;gt;0) and ((s2[t2]='*') or (s2[t2]='/')) then calcu;   <br />           inc(t2);s2[t2]:=c;   <br />           read(c);   <br />       end;   <br />       '(':<br />       begin <br />           inc(t2); <br />           s2[t2]:=c; <br />           read(c); <br />       end;   <br />       ')':  <br />       begin   <br />           while s2[t2]&amp;lt; &amp;gt;<br />       '(' do calcu;   <br />           dec(t2); <br />           read(c);   <br />       end;   <br />       '0'..'9':  <br />       begin   <br />           v:=0;   <br />           repeat   <br />              v:=10*v+ord(c)-ord('0');   <br />              read(c);   <br />           until (c&amp;lt; '0') or (c &amp;gt;'9');   <br />           inc(t1); <br />           s1[t1]:=v;   <br />       end;   <br />      end;   <br />      while t2 &amp;gt;0 do calcu;   <br />           writeln(s1[t1]); <br />end; </p><p>16.查找算法   <br />折半查找   <br />function binsearch(k:keytype):integer;   <br />var low,hig,mid:integer;   <br />begin   <br />    low:=1;<br />    hig:=n;   <br />    mid:=(low+hig) div 2;   <br />    while (a[mid].key&amp;lt; &amp;gt;k) and (low&amp;lt; =hig) do  <br />    begin   <br />         if a[mid].key &amp;gt;k then hig:=mid-1   <br />         else low:=mid+1;   <br />              mid:=(low+hig) div 2;   <br />         end;   <br />         if low &amp;gt;hig then mid:=0;   <br />            binsearch:=mid;   <br />end;     <br />树形查找   <br />二*排序树：每个结点的值都大于其左子树任一结点的值而小于其右子树任一结点的值。   <br />查找   <br />function treesrh(k:keytype):pointer;   <br />var q:pointer;   <br />begin   <br />    q:=root;   <br />    while (q&amp;lt; &amp;gt;nil) and (q^.key&amp;lt; &amp;gt;k) do   if k&amp;lt; <br />       q^.key then q:=q^.left   else q:=q^.right;   <br />    treesrh:=q;   <br />end;</p><img src ="http://www.blogjava.net/franlk/aggbug/47794.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">FRANLK 的个人空间</a> 2006-05-24 13:15 <a href="http://www.blogjava.net/franlk/articles/47794.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]一些基本算法1</title><link>http://www.blogjava.net/franlk/articles/47793.html</link><dc:creator>FRANLK 的个人空间</dc:creator><author>FRANLK 的个人空间</author><pubDate>Wed, 24 May 2006 05:13:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/47793.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/47793.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/47793.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/47793.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/47793.html</trackback:ping><description><![CDATA[摘录地址： <a href="http://vib.hit.edu.cn/vibbbs/dispbbs.asp?boardID=25&amp;ID=2357&amp;page=8">http://vib.hit.edu.cn/vibbbs/dispbbs.asp?boardID=25&amp;ID=2357&amp;page=8 </a><br />1.数论算法 <br />求两数的最大公约数 <br />function gcd(a,b:integer):integer; <br />begin<br />   if b=0 then gcd:=a <br />   else gcd:=gcd (b,a mod b); <br />end ; <br />求两数的最小公倍数 <br />function lcm(a,b:integer):integer;  <br />begin<br />   if a&amp;lt; b then swap(a,b); <br />      lcm:=a; <br />   while lcm mod b &amp;gt;<br />   0 do inc(lcm,a); <br />end; <br />素数的求法 <br />A.小范围内判断一个数是否为质数：  <br />function prime (n: integer): Boolean; <br />var I: integer; <br />begin <br />   for I:=2 to trunc(sqrt(n)) do <br />      if n mod I=0 then <br />      begin <br />         prime:=false; exit; <br />      end;   <br />   prime:=true;   <br />end;     <br />B.判断longint范围内的数是否为素数（包含求50000以内的素数表）：   <br />procedure getprime;   <br />var i,j:longint;   <br />    p:array[1..50000] of boolean;   <br />begin   <br />    fillchar(p,sizeof(p),true);   <br />    p[1]:=false;   <br />    i:=2;   <br />    while i&amp;lt; 50000 do   <br />    begin   <br />       if p[i] then   <br />       begin   <br />          j:=i*2;   <br />          while j&amp;lt; 50000 do   <br />          begin   <br />             p[j]:=false;   <br />             inc(j,i);   <br />          end;   <br />       end;   <br />       inc(i);   <br />    end;   <br />    l:=0;   <br />    for i:=1 to 50000 do   <br />       if p[i] then   <br />       begin   <br />          inc(l);  <br />          pr[l]:=i;   <br />       end;   <br />    end;{getprime}<br />   <br />function prime(x:longint):integer;   <br />var i:integer;   <br />begin   <br />    prime:=false;   <br />    for i:=1 to l do   <br />        if pr[i] &amp;gt;=x then break   <br />        else if x mod pr[i]=0 then exit;   <br />        prime:=true;   <br />end;{prime} <br />   <br />2.3.4.求最小生成树   <br />A.Prim算法：   <br />procedure prim(v0:integer);   <br />var lowcost,closest:array[1..maxn] of integer;   <br />    i,j,k,min:integer;   <br />begin   <br />    for i:=1 to n do   <br />    begin   <br />        lowcost[i]:=cost[v0,i];   <br />        closest[i]:=v0;   <br />    end;   <br />    for i:=1 to n-1 do   <br />    begin   {寻找离生成树最近的未加入顶点k}   <br />        min:=maxlongint;   <br />        for j:=1 to n do   <br />           if (lowcost[j]&amp;lt; min) and (lowcost[j]&amp;lt; &amp;gt;0) then   <br />           begin   <br />              min:=lowcost[j];   <br />              k:=j;   <br />           end;   <br />        lowcost[k]:=0; {将顶点k加入生成树}   <br />     {生成树中增加一条新的边k到closest[k]}   <br />     {修正各点的lowcost和closest值}   <br />     for j:=1 to n do   <br />         if cost[k,j]&amp;lt; lwocost[j] then   <br />         begin   <br />            lowcost[j]:=cost[k,j];   <br />            closest[j]:=k;   <br />         end;   <br />     end;   <br />end;{prim} <br /><p>B.Kruskal算法：(贪心) <br />    按权值递增顺序删去图中的边，若不形成回路则将此边加入最小生成树。 <br />function find(v:integer):integer; {返回顶点v所在的集合} <br />var i:integer; <br />begin   <br />    i:=1;   <br />    while (i&amp;lt; =n) and (not v in vset[i]) do inc(i);   <br />         if i&amp;lt; =n then find:=i   else find:=0; <br />end; </p><p>procedure kruskal; <br />var tot,i,j:integer; <br />begin   <br />   for i:=1 to n do vset[i]:=[i];{初始化定义n个集合，第I个集合包含一个元素I}   <br />       p:=n-1; q:=1; tot:=0; {p为尚待加入的边数，q为边集指针}   <br />       sort;   <br />   {对所有边按权值递增排序，存于e[i]中，e[i].v1与e[i].v2为边I所连接的两个顶点的序号，e[i].len为第I条边的长度}   <br />   while p &amp;gt;0 do   <br />   begin   <br />       i:=find(e[q].v1);<br />       j:=find(e[q].v2);   <br />       if i&amp;lt; &amp;gt;j then   <br />       begin   <br />          inc(tot,e[q].len);   <br />          vset[i]:=vset[i]+vset[j];<br />          vset[j]:=[];   <br />          dec(p);   <br />       end;   <br />       inc(q);   <br />   end;   </p><p>5.最短路径   </p><p>A.标号法求解单源点最短路径：   <br />var   a:array[1..maxn,1..maxn] of integer;   <br />      b:array[1..maxn] of integer; {b[i]指顶点i到源点的最短路径}   <br />      mark:array[1..maxn] of boolean;     <br />procedure bhf;   <br />var   best,best_j:integer;   <br />begin   <br />      fillchar(mark,sizeof(mark),false);   <br />      mark[1]:=true; <br />      b[1]:=0;{1为源点}   <br />      repeat   best:=0;   <br />      for i:=1 to n do   <br />          If mark[i] then {对每一个已计算出最短路径的点}   <br />          for j:=1 to n do   <br />              if (not mark[j]) and (a[i,j] &amp;gt;0) then   <br />                  if (best=0) or (b[i]+a[i,j]&amp;lt; best) then   <br />                  begin   <br />                      best:=b[i]+a[i,j]; best_j:=j;   <br />                  end;   <br />                  if best &amp;gt;0 then   <br />                  begin   <br />                      b[best_j]:=best;<br />                      mark[best_j]:=true;   <br />                  end;   <br />     until best=0;   <br />end;{bhf}     </p><p>B.Floyed算法求解所有顶点对之间的最短路径：   <br />procedure floyed;   <br />begin   <br />   for I:=1 to n do   <br />       for j:=1 to n do   <br />           if a[I,j] &amp;gt;0 then <br />              p[I,j]:=I else p[I,j]:=0;   <br />              {p[I,j]表示I到j的最短路径上j的前驱结点}   <br />              for k:=1 to n do {枚举中间结点}   <br />                  for i:=1 to n do   for j:=1 to n do   <br />                      if a[i,k]+a[j,k]&amp;lt; a[i,j] then   <br />                      begin   <br />                         a[i,j]:=a[i,k]+a[k,j];   <br />                         p[I,j]:=p[k,j];   <br />                      end;   <br />end; </p><p>C. Dijkstra 算法： <br />类似标号法，本质为贪心算法。 <br />var a:array[1..maxn,1..maxn] of integer; <br />    b,pre:array[1..maxn] of integer; {pre[i]指最短路径上I的前驱结点} <br />    mark:array[1..maxn] of boolean; <br />procedure dijkstra(v0:integer); <br />begin   <br />    fillchar(mark,sizeof(mark),false);   <br />    for i:=1 to n do   <br />    begin   <br />        d[i]:=a[v0,i];   <br />        if d[i]&amp;lt; &amp;gt;0 then <br />           pre[i]:=v0 <br />        else <br />           pre[i]:=0;   <br />    end;   <br />    mark[v0]:=true;   <br />    repeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数}   <br />        min:=maxint; <br />        u:=0; {u记录离1集合最近的结点}   <br />        for i:=1 to n do   <br />            if (not mark[i]) and (d[i]&amp;lt; min) then   <br />            begin   <br />               u:=i; min:=d[i];   <br />            end;   <br />            if u&amp;lt; &amp;gt;0 then   <br />            begin   <br />               mark[u]:=true;   <br />               for i:=1 to n do   <br />                   if (not mark[i]) and (a[u,i]+d[u]&amp;lt; d[i]) then   <br />                   begin   <br />                      d[i]:=a[u,i]+d[u];   <br />                      pre[i]:=u;   <br />                   end;   <br />               end;   <br />     until u=0; <br />end; </p><p>D.计算图的传递闭包 <br />Procedure Longlink; <br />Var T:array[1..maxn,1..maxn] of boolean; <br />Begin   <br />    Fillchar(t,sizeof(t),false);   <br />    For k:=1 to n do   <br />        For I:=1 to n do   <br />            For j:=1 to n do   <br />                T[I,j]:=t[I,j] or (t[I,k] and t[k,j]); <br />End;   </p><p>7.排序算法   </p><p>A.快速排序：   <br />procedure sort(l,r:integer);   <br />var i,j,mid:integer;   <br />begin   <br />    i:=l;j:=r; <br />    mid:=a[(l+r) div 2];   <br />    {将当前序列在中间位置的数定义为中间数}   <br />    repeat   <br />    while a[i]&amp;lt; mid do inc(i); {在左半部分寻找比中间数大的数}   <br />    while mid&amp;lt; a[j] do dec(j);{在右半部分寻找比中间数小的数}   <br />    if i&amp;lt; =j then   <br />    begin {若找到一组与排序目标不一致的数对则交换它们}   <br />       swap(a[i],a[j]);   <br />       inc(i);<br />       dec(j); {继续找}   <br />    end;   <br />    until i &amp;gt;j;   <br />    if l&amp;lt; j then <br />       sort(l,j); {若未到两个数的边界，则递归搜索左右区间}   <br />    if i&amp;lt; r then sort(i,r);   <br />end;{sort} </p><p>B.插入排序： </p><p>procedure insert_sort(k,m:word); {k为当前要插入的数，m为插入位置的指针} <br />var i:word; p:0..1; <br />begin   <br />    p:=0;   <br />    for i:=m downto 1 do   <br />        if k=a[i] then exit;   <br />        repeat   If k &amp;gt;a[m] then   <br />                 begin   <br />                    a[m+1]:=k; p:=1;   <br />                 end   <br />                 else   <br />                 begin   <br />                    a[m+1]:=a[m]; <br />                    dec(m);   <br />                 end;   <br />        until p=1; <br />end;{insert_sort}   <br />l 主程序中为：   <br />   a[0]:=0;   <br />   for I:=1 to n do insert_sort(b[i],I-1);     </p><p>C.选择排序：   <br />procedure sort;   <br />var i,j,k:integer;   <br />begin   <br />     for i:=1 to n-1 do   <br />     begin   <br />         k:=i;   <br />         for j:=i+1 to n do   <br />            if a[j]&amp;lt; a[k] then <br />               k:=j; {找出a[i]..a[n]中最小的数与a[i]作交换}   <br />               if k&amp;lt; &amp;gt;i then   <br />               begin   <br />                  a[0]:=a[k];<br />                  a[k]:=a[i];<br />                  a[i]:=a[0];   <br />               end;   <br />     end;   <br />end;     </p><p>D. 冒泡排序   <br />procedure sort;   <br />var i,j,k:integer;   <br />begin   <br />    for i:=n downto 1 do   <br />        for j:=1 to i-1 do   <br />            if a[j] &amp;gt;a[i] then   <br />            begin   <br />               a[0]:=a[i];<br />               a[i]:=a[j];<br />               a[j]:=a[0];   <br />            end;   <br />end;     </p><p>E.堆排序：   <br />procedure sift(i,m:integer);{调整以i为根的子树成为堆,m为结点总数}   <br />var k:integer;   <br />begin   <br />    a[0]:=a[i]; <br />    k:=2*i;{在完全二*树中结点i的左孩子为2*i,右孩子为2*i+1}   <br />    while k&amp;lt; =m do   <br />    begin   <br />        if (k&amp;lt; m) and (a[k]&amp;lt; a[k+1]) then inc(k);{找出a[k]与a[k+1]中较大值}   <br />        if a[0]&amp;lt; a[k] then   <br />        begin   <br />           a[i]:=a[k];<br />           i:=k;<br />           k:=2*i;   <br />        end   <br />        else <br />           k:=m+1;   <br />        end;   <br />        a[i]:=a[0]; {将根放在合适的位置}   <br />end; </p><p>procedure heapsort; <br />var j:integer; <br />begin   <br />    for j:=n div 2 downto 1 do sift(j,n);   <br />        for j:=n downto 2 do   <br />        begin   <br />            swap(a[1],a[j]);   <br />            sift(1,j-1);   <br />        end; <br />end; </p><p>F. 归并排序 <br />{a为序列表，tmp为辅助数组} <br />procedure merge(var a:listtype; p,q,r:integer); <br />{将已排序好的子序列a[p..q]与a[q+1..r]合并为有序的tmp[p..r]} <br />var I,j,t:integer; <br />    tmp:listtype; <br />begin   <br />    t:=p;<br />    i:=p;<br />    j:=q+1;{t为tmp指针，I,j分别为左右子序列的指针}   <br />    while (t&amp;lt; =r) do   <br />    begin   <br />       if (i&amp;lt; =q){左序列有剩余} and ((j &amp;gt;r) or (a[i]&amp;lt; =a[j])) then  {满足取左边序列当前元素的要求}   <br />       begin   <br />          tmp[t]:=a[i]; inc(i);   <br />       end   <br />       else   <br />       begin   <br />          tmp[t]:=a[j];<br />          inc(j);   <br />       end;   <br />       inc(t);   <br />    end;   <br />    for i:=p to r do a[i]:=tmp[i]; <br />end;{merge} </p><p>procedure merge_sort(var a:listtype; p,r: integer); {合并排序a[p..r]} <br />var q:integer; <br />begin   <br />    if p&amp;lt; &amp;gt;r then   <br />    begin   <br />       q:=(p+r-1) div 2;   <br />       merge_sort (a,p,q);   <br />       merge_sort (a,q+1,r);   <br />       merge (a,p,q,r);   <br />    end; <br />end; <br />{main} <br />begin   <br />    merge_sort(a,1,n); <br />end. </p><p><br />   writeln(tot); <br />end;       <br /><br /></p><img src ="http://www.blogjava.net/franlk/aggbug/47793.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">FRANLK 的个人空间</a> 2006-05-24 13:13 <a href="http://www.blogjava.net/franlk/articles/47793.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>