必背经典算法(pascal)
- 格式:doc
- 大小:127.50 KB
- 文档页数:24
算法设计初步与典型试题枚举搜索 (4)1、枚举数字 (5)3、百钱买百鸡 (5)4、分书问题 (6)逻辑判断 (7)5、谁是小偷 (7)6、质量评比 (7)7、谁获冠军 (8)8、四大淡水湖 (9)递推法 (10)9、【菲波纳葜数列】 (10)10、递推关系的应用“杨辉三角” (10)11、蜜蜂爬行 (11)13、铺骨牌(2000年全国联赛初赛) (12)倒退 (13)14、贮油点 (13)枚举素数 (14)15、素数 (14)16、歌德巴赫猜想 (15)17、计算真因子 (16)筛法 (17)18、求素数(95年,全国联赛初赛) (17)19、用筛法统计楼梯级数 (18)最大公约数与最小公倍数 (19)20.求两个正整数的最大公约数 (19)21、求两个正整数的最小公倍数 (19)进制转换 (21)22、十进制转换为n进制 (21)23. N进制数转化为十制数 (22)循环问题 (23)24、猴子选大王 (23)25、狐狸捉兔子 (24)26、约瑟环 (25)数组 (25)27、求递增和递减子序列 (27)28、马鞍数 (28)29、数学黑洞6174 (29)方阵填数 (30)30、方阵填数 (30)31、蛇形矩阵: (31)字符数组与字符串 (32)一、定义 (32)二、字符串的常用内部函数和过程 (33)三、字符数组与字符串应用 (33)36、寻找单词 (36)37、【题目】从键盘输入一个长度不超过40的字符串,按要求进行删除. (37)数组与字符串应用 (38)38、高精度加法程序 (38)39、回文算术 (39)递归算法 (41)40、利用递归调用手段编程计算N!。
(42)41、利用递归调用技术求菲波纳葜数列的第N项。
(42)42、输入一串以‘.’结束的字符,按逆序输出。
(44)43、用递归函数求最大公约数 (44)44、汉诺塔 (45)嵌套 (47)45、三齿轮问题 (47)搜索算法(回溯、深度优先) (48)46、八皇后问题 (48)47、求N个数的全排列 (49)48、跳马问题(骑士遍历) (50)49、深度优先搜索解分书问题 (53)50、四色问题。
pascal三角形选法-回复什么是[pascal三角形选法]?Pascal三角形选法是一种用于组合数学中的计算方法,以法国数学家布莱兹·帕斯卡(Blaise Pascal)的名字命名。
这个方法可以用来计算组合数,即从一个给定的集合中选取固定数量元素的方式数目。
在Pascal三角形中,每一行的数字都是通过相邻上一行的数字计算得到的。
具体计算方法为,每个数字等于上一行对应位置数字与它的左上方数字之和。
这样,Pascal三角形便呈现出一种对称的形状,每一行的数字在从左到右和从右到左的数值分布上都是对称的。
该选法可以通过直接查找Pascal三角形中的数字来计算组合数。
例如,如果要计算从一个集合中选取3个元素的组合数,可以在第4行(从0开始计数)中找到对应位置的数字,并将其作为结果。
如何应用[pascal三角形选法]?首先,要利用这个选法,我们需要构建一个Pascal三角形。
构建Pascal 三角形的方法是,将上一行的相邻两个数字相加,将其和作为下一行相应位置的数字。
开始时,我们可以将第一行的数字设置为1,并依次计算后续行的数字。
这样,我们就可以得到一个完整的Pascal三角形。
接下来,我们可以使用构建好的Pascal三角形来计算组合数。
假设我们要计算从一个集合中选取r个元素的组合数。
我们可以在Pascal三角形中的第r+1行(从0开始计数)找到对应位置的数字,这个数字就是我们要的结果。
举个例子来说明。
假设我们有一个集合{1, 2, 3, 4, 5, 6, 7, 8},我们要从中选取3个元素的组合数。
首先,我们构建一个Pascal三角形。
第一行:1第二行:1 1第三行:1 2 1第四行:1 3 3 1由于我们要选择3个元素,所以我们需要查找Pascal三角形中的第4行。
从左往右数第3个数字是3,所以从给定集合中选取3个元素的组合数为3。
这就是Pascal三角形选法的基本思想和应用方法。
为什么要使用[pascal三角形选法]?Pascal三角形选法提供了一种简洁且高效的计算组合数的方法。
算法:
算法是程序的基础。
有了一个好的算法,再进行编码,把算法转换成任何一个程序设计语言所表示的程序。
算法就是解题步骤。
例题:求1——100这一百个相继整数的和S。
解法一:s=1+2+3+……+100 【需要100-1次加法】
解法二:s=(1+100)*50 【需要加法、乘法、除法各一次】不同的算法,对计算的工作量造成重大影响,还要考虑算法对精确度的影响。
程序质量的高低,主要取决于算法。
结构化程序特点:
1按功能相对独立原则划分若干模块。
2 单入口、单出口。
3 强调三种基本结构组成(顺序、选择、循环性)。
4 书写格式清晰。
5 不包含无限循环(即执行时间是有限的)
6 没有死语句(即程序中所有语句都能得到执行的机会)
设计结构化程序方法:
1 自顶向下
2 逐步细化。
3 按“功能单一”原则划分模块。
第九讲 分治算法一、分治思想分治思想融入于常见算法的各个角落,简单点说,所谓的分治,实际上是将一个问题拆成若干个小问题,将它们分别解决后,就等价于解决了整个问题。
二、快速幂算法与分治思想(底下部分的^表示乘方)求2^233(mod 1,000,000,007)这个问题我们可以这么考虑2^233 = 2^116 * 2^116 * 2那么原来问题就转化为求2^116(mod 1,000,000,007)就这样下去,我们只要求得2^52即可,也就是说2^26即可换句话说,我们求得2^13即可,也就是说2^6 * 2^6 * 22^6 = 2^3 * 2^32^3 = 2^1 * 2^1 * 2 = 8所以2^6 = 8*8=642^13 = 2^6 * 2^6 * 2 = 64 * 64 * 2 = 8192就这样…我们逐步回推,可以得到2^233当然注意要取模*你可以说这个算法是递归,但是这个也可以说是”拆成若干个小问题”*三、一道NOIP2007的例题本题摘自NOIP 2007 普及组初赛(完善程序第二题) 大家可以暂时思考一下本题中,我们只要求构造一种方案所以,这个题我们可以采取分治的策略来解决首先,我们思考一下,这一题的特殊条件1,我们用的是2的k次方*2的k次方的格子2,这一题中,有一个”-1”的存在那么,我们就可以用一种特殊的策略首先,如果k=0,那么……就不用构造了,皆大欢喜所以,我们想办法将2^k改为2^(k-1)即可我们可以将原来的正方形切成四个,如右图所以,这时候,我们可以将三个”1”当作-1,带入到右上,右下,左下处理,将”-1”依旧留在左上角这样,问题就转化成了一个2^(k-1)规模的然后..(本图中为了较为清晰的显示,将13~16与18~21略去了)所以,这样就将原来问题分治出来了那么,这一个问题就得到了解决四、一道来自codeforces的例题这一题摘自Codeforces 321C题面:英文版:C. Ciel the Commandertime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputNow Fox Ciel becomes a commander of Tree Land. Tree Land, like its name said, has n cities connected byn - 1 undirected roads, and for any two cities there always exists a path between them.Fox Ciel needs to assign an officer to each city. Each officer has a rank — a letter from 'A' to 'Z'. So there will be 26 different ranks, and 'A' is the topmost, so 'Z' is the bottommost.There are enough officers of each rank. But there is a special rule must obey: if x and y are two distinct cities and their officers have the same rank, then on the simple path between x and y there must be a city z that has an officer with higher rank. The rule guarantee that a communications between same rank officers will be monitored by higher rank officer.Help Ciel to make a valid plan, and if it's impossible, output "Impossible!".InputThe first line contains an integer n (2 ≤ n ≤ 105) — the number of cities in Tree Land.Each of the following n - 1 lines contains two integers a and b (1 ≤ a, b ≤ n, a ≠ b) — they mean that there will be an undirected road between a and b. Consider all the cities are numbered from 1 to n.It guaranteed that the given graph will be a tree.OutputIf there is a valid plane, output n space-separated characters in a line — i-th character is the rank of officer in the city with number i.Otherwise output "Impossible!".Examplesinput41 21 31 4outputA B B Binput101 22 33 44 55 66 77 88 99 10outputD C B A D C B D C DNoteIn the first example, for any two officers of rank 'B', an officer with rank 'A' will be on the path between them. So it is a valid solution.中文题意:给你n个点,求构造一个方案,使得每个点存在一个’A’到’Z’的权值任意两个权值为x(x从’A’到’Z’)的点之间,一定存在至少一个权值比x大的点如果无解,输出”Impossible!”注意:’A’比’B’~’Z’大,’B’比’C’~’Z’大……’Y’比’Z’大如果不懂,可以观察样例所以,这道题我们该怎么做呢?我们仔细观察‘A’是最大的,也就是说,最多只有一个’A’那么我们每次选一个点,将它当作最大的点,然后,将它的其他部分”解离”也就是说,将它的其他部分分开处理这样,就可以解决了这题红点为A,然后将绿色点当B/C*但是,怎么找这个点呢*我们可以在这个树里面,随机一个点,但是是有可能得出无解我们这时候,只要找出”树的重心”即可这个树的重心可以百度得到……。
(迭起来有:望有界:1function CPAIR2(S);beginif |S|=2 then δ:=S中这2点的距离else if |S|=0then δ:=∞else begin1. m:=S中各点x坐标值的中位数;构造S1和S2,使S1={p∈S|px≤m}和S2={p∈S|px>m}2. δ1:=CPAIR2(S1);δ2:=CPAIR2(S2);3. δm:=min(δ1,δ2);4. 设P1是S1中距垂直分割线l的距离在δm之内的所有点组成的集合,P2是S2中距分割线l的距离在δm之内所有点组成的集合。
将P1 和P2中的点依其y坐标值从小到大排序,并设P1*和P2*是相应的已排好序的点列;5. 通过扫描P1*以及对于P1*中每个点检查P2*中与其距离在δm之内的所有点(最多6个)可以完成合并。
当P1*中的扫描指针逐次向上移动时,P2*中的扫描指针可在宽为2δm的一个区间内移动。
设δl是按这种扫描方式找到的点对间的最小距离;6. δ=min(δm,δl);end;return(δ);end;下面我们来分析一下算法CPAIR2的计算复杂性。
设对于n个点的平面点集S,算法耗时T(n)。
算法的第1步和第5步用了O(n)时间,第3步和第6步用了常数时间,第2步用了2T(n/2)时间。
若在每次执行第4步时进行排序,则在最坏情况下第4步要用O(n log n)时间。
这不符合我们的要求。
因此,在这里我们要作一个技术上的处理。
我们采用设计算法时常用的预排序技术,即在使用分治法之前,预先将S中n个点依其y坐标值排好序,设排好序的点列为P*。
在执行分治法的第4步时,只要对P*作一次线性扫描,即可抽取出我们所需要的排好序的点列P1*和P2*。
然后,在第5步中再对P1*作一次线性扫描,即可求得δl。
因此,第4步和第5步的两遍扫描合在一起只要用O(n)时间。
这样一来,经过预排序处理后的算法CPAIR2所需的计算时间T(n)满足递归方程:显而易见T(n)=O(n log n),预排序所需的计算时间为O(n1og n)。
1.快排procedure quicksort(l,r:longint);{从L到R排序}vari,j,mid:longint;begini:=l;{首标记}j:=r;{尾标记}mid:=a[ (l+r) div 2];{中间值}repeatwhile a[i]<mid do inc(i);{找到不合顺序的a[i]}while a[j]>mid do dec(j);{找到不合顺序的a[j]}if i<=j then begin{交换}swap(a[i],a[j]);inc(i);dec(j);end;until i>j;if l<j then quicksort(l,j);{递归,排L到j之间的数}if i<r then quicksort(i,r);{递归,排L到j之间的数}end;2.高精度加法:typehp=array[0..200] of longint;procedure g_jia_g(a,b:hp;var c:hp);varlen,i:longint;beginfillchar(c,sizeof(c),0);if a[0]>b[0] then len:=a[0] else len:=b[0];{len=答案的长度}for i:=1 to len do{加的过程}beginc[i]:=a[i]+b[i]+c[i];if c[i]>=10 then begin{进位}c[i]:=c[i]-10;c[i+1]:=c[i+1]+1;end;end;c[0]:=len+1;{判断最高位是否进位}f c[len+1]=0 then c[0]:=c[0]-1;end;3.压位高精度加法typehp=array[0..200] of longint; {每个单位存100000000之内的数(1*10^8,即1后8个0)}procedure init;{读入的过程}begina[0]:=(l1-1) div 8+1;{第一个加数的长度}b[0]:=(l2-1) div 8+1;{第二个加数的长度}for i:=1 to l1 do{读入加数a的过程}a[(l1-i) div 8+1]:= a[(l1-i) div 8+1]*10+ord(s1[i])-48;for i:=1 to l2 do{读入加数b的过程}b[(l2-i) div 8+1]:=b[(l2-i) div 8+1]*10+ord(s2[i])-48;end;procedure hiadd(a,b:hp;var c:hp);beginfillchar(c,sizeof(c),0);if a[0]>b[0] then c[0]:=a[0] else c[0]:=b[0];{加数长度}for i:=1 to c[0] do{加的过程}c[i]:=c[i]+a[i]+b[i];for i:=1 to c[0] do{进位}begininc(c[i+1],c[i] div 100000000);c[i]:=c[i] mod 100000000;end;if c[c[0]+1]>0 then inc(c[0]);{判断最高位是否有进位}end;procedure print;{输出过程}beginwrite(c[c[0]]);{输出最高位}for i:=c[0]-1 downto 1 dobeginif c[i] div 10000000=0 then write(0);if c[i] div 1000000=0 then write(0);if c[i] div 100000=0 then write(0);if c[i] div 10000=0 then write(0);if c[i] div 1000=0 then write(0);if c[i] div 100=0 then write(0);if c[i] div 10=0 then write(0);write(c[i]);end;end;4.高精度乘法typehp=array[0..200] of longint;procedure g_cheng_g(a,b:hp;var c:hp);varlen,i,j:longint;beginfillchar(c,sizeof(c),0);for i:=1 to a[0] do{累乘+进位过程}for j:=1 to b[0] dobeginc[i+j-1]:=c[i+j-1]+a[i]*b[j];c[i+j]:=c[i+j]+c[i+j-1] div 10;c[i+j-1]:=c[i+j-1] mod 10;end;len:=a[0]+b[0]+1;{结果长度}while (c[len]=0) and (len>1) do dec(len);{判断最高位是否为零} c[0]:=len;end;5.压位高精度乘法typehp=array[0..200] of longint;procedure init;{读入过程}begina[0]:=(l1-1)div 4+1;{加数a的长度}b[0]:=(l2-1)div 4+1;{加数b的长度}for i:=1 to l1 do{读入a}a[(l1-i)div 4+1] :=a[(l1-i)div 4+1]*10+ord(s1[i])-48;for i:=1 to l2 do{读入b}b[(l2-i)div 4+1] :=b[(l2-i)div 4+1]*10+ord(s2[i])-48;end;procedure yacheng(a,b:hp;var c:hp);beginfillchar(c,sizeof(c),0);for i:=1 to a[0] do{累乘+进位过程}for j:=1 to b[0] dobeginc[i+j-1]:=c[i+j-1]+a[i]*b[j];c[i+j]:=c[i+j]+c[i+j-1] div 10000;c[i+j-1]:=c[i+j-1] mod 10000;end;c[0]:=a[0]+b[0]-1;{最高位是否进位}while c[c[0]+1]>0 dobegininc(c[0]);c[c[0]+1]:=c[c[0]+1]+c[c[0]] div 10000;c[c[0]]:=c[c[0]] mod 10000;end;end;procedure print;{输出过程}beginwrite(c[c[0]]);for i:=c[0]-1 downto 1 dobeginif c[i] div 1000=0 then write(0);if c[i] div 100=0 then write(0);if c[i] div 10=0 then write(0);write(c[i]);end;end;6.二分法查找procedure found(x,top,last:longint);{从top与last之间找x(a数组必须有序)} beginif top<=last thenbeginmid:=(top+last) div 2;{中间的下标}if x=a[mid] then writeln(mid){找到了}else if x<a[mid] then found(x,top,mid-1){在前面}else found(x,mid+1,last);{在后面} endelse writeln('not found');{a中没有x}end;7.斐波那契数列function f(x:longint):longint;{输出斐波那契中的第x项}beginif x=0 then f:=0else if x=1 then f:=1else if x=2 then f:=1else f:=f(x-1)+f(x-2);end;8.判断素数function pdss(x:longint):boolean;vari:longint;beginif (x=0) or (x=1) then exit(false);{0和1不是素数}if (x=2) or (x=3) then exit(true);{2和3是素数}for i:=2 to trunc(sqrt(x)) doif x mod i =0 then exit(false);exit(true);end;9.分解质因数成表格形式{2——2 3——1 5——1 =2*2*3*5=60}procedure fat(x:longint;var a:arr;var s:longint);begini:=1; {最小的因子}s:=0;repeatinc(i);{因子加1}if x mod i=0 thenbegininc(s);{标记加1}a[s,1]:=i;{因子}a[s,2]:=0;{因子个数清零}while x mod i=0 do begin inc(a[s,2]); x:=x div i; end;{去除该因子} end;until x=1;end;10.十进制化二进制procedure s_e(n:longint);{除2取余法}vari:longint;begin{1770}read(n);i:=0;while n<>0 dobegina[i]:=n mod 2;i:=i+1;n:=n div 2;end;end.11.最大公约数function gcd(a,b:integer):integer;beginif b=0 then gcd:=aelse gcd:=gcd (b,a mod b);{辗转相除法}end;12.最小公倍数function lcm(a,b:integer):integer;beginif a<b then swap(a,b);lcm:=a;while lcm mod b>0 do inc(lcm,a);end;13.全排列procedure solve(dep:integer);var i:integer;beginif dep=n+1 thenbeginwriteln(s);exit;end;for i:=1 to n doif not used[i] thenbegins:=s+chr(i+ord('0'));used[i]:=true;solve(dep+1);s:=copy(s,1,length(s)-1);used[i]:=false;end;end;14.背包DPprogram bb2;varxk,n,i,j:longint;w,c:array[1..100] of longint;f:array[0..101,0..100001] of longint;function max(x,y:longint):longint;beginif x>y then exit(x) else exit(y);end;beginassign(input,'bb2.in');assign(output,'bb2.out');reset(input);rewrite(output);readln(xk,n);for i:=1 to n doreadln(w[i],c[i]);{f[i,j] 第i个物品,重量是j 的最大价值}fillchar(f,sizeof(f),0);for i:=1 to n dofor j:=1 to xk doif j>=w[i] then f[i,j]:=max( f[i-1,j] , f[i-1,j-w[i]]+c[i] )else f[i,j]:=f[i-1,j];write(f[n,xk]);close(input);close(output);end.。
Pascal经典教程(1—3章)⽆论做任何事情,都要有⼀定的⽅式⽅法与处理步骤。
计算机程序设计⽐⽇常⽣活中的事务处理更具有严谨性、规范性、可⾏性。
为了使计算机有效地解决某些问题,须将处理步骤编排好,⽤计算机语⾔组成“序列”,让计算机⾃动识别并执⾏这个⽤计算机语⾔组成的“序列”,完成预定的任务。
将处理问题的步骤编排好,⽤计算机语⾔组成序列,也就是常说的编写程序。
在Pascal语⾔中,执⾏每条语句都是由计算机完成相应的操作。
编写Pascal程序,是利⽤Pascal语句的功能来实现和达到预定的处理要求。
“千⾥之⾏,始于⾜下”,我们从简单程序学起,逐步了解和掌握怎样编写程序。
程序结构和基本语句在未系统学习Pascal语⾔之前,暂且绕过那些繁琐的语法规则细节,通过下⾯的简单例题,可以速成掌握Pascal程序的基本组成和基本语句的⽤法,让初学者直接模仿学习编简单程序。
[例1.1]编程在屏幕上显⽰“Hello World!”。
Pascal程序:Program ex11;BeginWriteln(‘Hello World!’);ReadLn;End.这个简单样例程序,希望⼤家的程序设计学习能有⼀个良好的开端。
程序中的Writeln是⼀个输出语句,它能命令计算机在屏幕上输出相应的内容,⽽紧跟Writeln语句后是⼀对圆括号,其中⽤单引号引起的部分将被原原本本地显⽰出来。
[例1.2]已知⼀辆⾃⾏车的售价是300元,请编程计算a辆⾃⾏车的总价是多少?解:若总售价⽤m来表⽰,则这个问题可分为以下⼏步处理:①从键盘输⼊⾃⾏车的数⽬a;②⽤公式 m=300*a 计算总售价;③输出计算结果。
Pascal程序:Program Ex12; {程序⾸部}Var a,m : integer; {说明部分}Begin {语句部分}Write(‘a=’);ReadLn(a); {输⼊⾃⾏车数⽬}M := 300*a; {计算总售价}Writeln(‘M=’,m); {输出总售价}ReadLn; {等待输⼊回车键}End.此题程序结构完整,从中可看出⼀个Pascal 程序由三部分组成:(1)程序⾸部由保留字Program开头,后⾯跟⼀个程序名(如:Exl1);其格式为:Program 程序名;程序名由⽤户⾃⼰取,它的第⼀个字符必须是英⽂字母,其后的字符只能是字母或数字和下划线组成,程序名中不能出现运算符、标点符和空格。
一、数论算法1.求两数的最大公约数function gcd(a,b:integer):integer;beginif b=0 then gcd:=aelse gcd:=gcd (b,a mod b);end ;2.求两数的最小公倍数function lcm(a,b:integer):integer;beginif a<b then swap(a,b);lcm:=a;while lcm mod b>0 do inc(lcm,a);end;3.素数的求法A.小范围内判断一个数是否为质数:function prime (n: integer): Boolean;var I: integer;beginfor I:=2 to trunc(sqrt(n)) doif n mod I=0 then beginprime:=false; exit;end;prime:=true;end;B.判断longint范围内的数是否为素数(包含求50000以内的素数表): procedure getprime;vari,j:longint;p:array[1..50000] of boolean;beginfillchar(p,sizeof(p),true);p[1]:=false;i:=2;while i<50000 do beginif p[i] thenbeginj:=i*2;while j<50000 dobegin {筛选法}p[j]:=false;inc(j,i);end;end;inc(i);end;l:=0;for i:=1 to 50000 doif p[i] then begininc(l);pr[l]:=i;end;end;{getprime}function prime(x:longint):boolean;var i:integer;beginprime:=false;for i:=1 to l doif pr[i]>=x then breakelse if x mod pr[i]=0 then exit;prime:=true;end;{prime}二、图论算法1.最小生成树A.Prim算法:procedure prim(v0:integer);varlowcost,closest:array[1..maxn] of integer;i,j,k,min:integer;beginfor i:=1 to n do beginlowcost:=cost[v0,i];closest:=v0;end;for i:=1 to n-1 do begin{寻找离生成树最近的未加入顶点k}min:=maxlongint;for j:=1 to n doif (lowcost[j]<min) and (lowcost[j]<>0) then begin min:=lowcost[j];k:=j;end;lowcost[k]:=0; {将顶点k加入生成树}{生成树中增加一条新的边k到closest[k]}{修正各点的lowcost和closest值}for j:=1 to n doif cost[k,j]<lwocost[j] then beginlowcost[j]:=cost[k,j];closest[j]:=k;end;end;end;{prim}B.Kruskal算法:(贪心)按权值递增顺序删去图中的边,若不形成回路则将此边加入最小生成树。
function find(v:integer):integer; {返回顶点v所在的集合}var i:integer;begini:=1;while (i<=n) and (not v in vset) do inc(i);if i<=n then find:=i else find:=0;end;procedure kruskal;vartot,i,j:integer;beginfor i:=1 to n do vset:=;{初始化定义n个集合,第I个集合包含一个元素I}p:=n-1; q:=1; tot:=0; {p为尚待加入的边数,q为边集指针}sort;{对所有边按权值递增排序,存于e中,e.v1与e.v2为边I所连接的两个顶点的序号,e.len为第I条边的长度}while p>0 do begini:=find(e[q].v1);j:=find(e[q].v2);if i<>j then begininc(tot,e[q].len);vset:=vset+vset[j];vset[j]:=[];dec(p);end;inc(q);end;writeln(tot);end;2.最短路径A.标号法求解单源点最短路径:vara:array[1..maxn,1..maxn] of integer;b:array[1..maxn] of integer; {b指顶点i到源点的最短路径}mark:array[1..maxn] of boolean;procedure bhf;varbest,best_j:integer;beginfillchar(mark,sizeof(mark),false);mark[1]:=true; b[1]:=0;{1为源点}repeatbest:=0;for i:=1 to n doIf mark then {对每一个已计算出最短路径的点}for j:=1 to n doif (not mark[j]) and (a[i,j]>0) thenif (best=0) or (b+a[i,j]<best) then beginbest:=b+a[i,j]; best_j:=j;end;if best>0 then beginb[best_j]:=best;mark[best_j]:=true;end;until best=0;end;{bhf}B.Floyed算法求解所有顶点对之间的最短路径:procedure floyed;beginfor I:=1 to n dofor j:=1 to n doif a[I,j]>0 then p[I,j]:=I else p[I,j]:=0; {p[I,j]表示I到j的最短路径上j的前驱结点}for k:=1 to n do {枚举中间结点}for i:=1 to n dofor j:=1 to n doif a[i,k]+a[j,k]<a[i,j] then begina[i,j]:=a[i,k]+a[k,j];p[I,j]:=p[k,j];end;end;C. Dijkstra 算法:vara:array[1..maxn,1..maxn] of integer;b,pre:array[1..maxn] of integer; {pre指最短路径上I的前驱结点} mark:array[1..maxn] of boolean;procedure dijkstra(v0:integer);beginfillchar(mark,sizeof(mark),false);for i:=1 to n do begind:=a[v0,i];if d<>0 then pre:=v0 else pre:=0;end;mark[v0]:=true;repeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数}min:=maxint; u:=0; {u记录离1集合最近的结点}for i:=1 to n doif (not mark) and (d<min) then beginu:=i; min:=d;end;if u<>0 then beginmark[u]:=true;for i:=1 to n doif (not mark) and (a[u,i]+d[u]<d) then begind:=a[u,i]+d[u];pre:=u;end;end;until u=0;end;3.计算图的传递闭包Procedure Longlink;VarT:array[1..maxn,1..maxn] of boolean;BeginFillchar(t,sizeof(t),false);For k:=1 to n doFor I:=1 to n doFor j:=1 to n do T[I,j]:=t[I,j] or (t[I,k] and t[k,j]);End;4.无向图的连通分量A.深度优先procedure dfs ( now,color: integer);beginfor i:=1 to n doif a[now,i] and c=0 then begin {对结点I染色}c:=color;dfs(I,color);end;end;B 宽度优先(种子染色法)5.关键路径几个定义:顶点1为源点,n为汇点。
a. 顶点事件最早发生时间Ve[j], Ve [j] = max{ Ve [j] + w[I,j] },其中Ve (1) = 0;b. 顶点事件最晚发生时间 Vl[j], Vl [j] = min{ Vl[j] – w[I,j] },其中 Vl(n) = Ve(n);c. 边活动最早开始时间 Ee, 若边I由<j,k>表示,则Ee = Ve[j];d. 边活动最晚开始时间 El, 若边I由<j,k>表示,则El = Vl[k] – w[j,k]; 若 Ee[j] = El[j] ,则活动j为关键活动,由关键活动组成的路径为关键路径。
求解方法:a. 从源点起topsort,判断是否有回路并计算Ve;b. 从汇点起topsort,求Vl;c. 算Ee 和 El;6.拓扑排序找入度为0的点,删去与其相连的所有边,不断重复这一过程。
例寻找一数列,其中任意连续p项之和为正,任意q 项之和为负,若不存在则输出NO.7.回路问题Euler回路(DFS)定义:经过图的每条边仅一次的回路。
(充要条件:图连同且无奇点)Hamilton回路定义:经过图的每个顶点仅一次的回路。
一笔画充要条件:图连通且奇点个数为0个或2个。
9.判断图中是否有负权回路 Bellman-ford 算法x,y,t分别表示第I条边的起点,终点和权。
共n个结点和m条边。
procedure bellman-fordbeginfor I:=0 to n-1 do d:=+infinitive;d[0]:=0;for I:=1 to n-1 dofor j:=1 to m do {枚举每一条边}if d[x[j]]+t[j]<d[y[j]] then d[y[j]]:=d[x[j]]+t[j];for I:=1 to m doif d[x[j]]+t[j]<d[y[j]] then return false else return true;end;10.第n最短路径问题*第二最短路径:每举最短路径上的每条边,每次删除一条,然后求新图的最短路径,取这些路径中最短的一条即为第二最短路径。