清华内部ACM培训资料-各类经典算法

合集下载

ACM经典算法

ACM经典算法

ACM竞赛经典算法计算机与信息技术学院目录第一次课递归 (3)第二次课排列 (6)第三次课经典排列 (9)第四次课深度搜索 (15)第五次课深搜2 (23)第六次课深搜(3) (26)第七次课深搜(4) (33)第八次课宽搜(1) (41)第九次课宽搜(2)+双向搜索 (47)第十次课启发式搜索A*(宽搜的变式) (54)ACM 竞赛经典算法第一课递归一、pascal 特点:1. 编写程序结构化;2. 支持递归;3. 通过使用指针,实现动态存储。

二、函数和过程的作用:1. 相对独立功能的一段程序,一般用一个子程序(函数和过程)来编写;2. 结构清楚,便于调试、修改和扩充;3. 节约程序段和内存;三、递归定义:子程序自己调用自己的程序段叫递归;使用递归的条件1. 可以把一个问题转化为一个类似自己的新问题,且问题的规模发生规律性的变化。

2. 可以通过转化使问题得到解决。

3. 有一个明确的结束条件。

递归实际上是个逆向思维过程,核心是求递归公式。

四、习题:1、 用递归求n!.程序如下:program sample1_1;varn:integer;function fac (n:integer ):beginif n=1 then begin fac:=1;exit;end;fac:=n*fac(n-1);end;begin readln(n); end.总结:1、 递归一般用函数或过程来实现,主程序没有办法来实现递归;2、 递归要有空间想象能力;3、 需要保护的变量一定要开成局部变量。

像function fac( n:integer )中的n.就是局部变量。

2、斐波那契数列f(n)=f(n-1)+f(n-2)程序如下:varn:integer;function f(n:integer):integer;beginif (n=1) or(n=0) then begin f:=1;exit;end;f(n):=f(n-1)+f(n-2);end;beginreadln(n);write(f(n));end.总结:(1)递归每执行一次,就要开辟一次局部变量,保护上一次的内容。

清华大学ACM题解

清华大学ACM题解
{
if (k==n){ //Output permutation.
for (int i-1; i<n; i++) cout<<a[i]<<" ";
}
else //a[k:n] has more than one permutation.
// Generate these recursively.
{
int a[3] = {1, 2, 3};
Perm(a, 0, 3);
return 0;
}
该程序的运行结果为
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2
那么,该函数就完成了对一个数组进行全排列的操作
下面,分析该程序,我用圆圈代表每次函数的调用
对于数据的输入和输出有几道练习题
/showproblem.php?pid=1089

/showproblem.php?pid=1096
二、算法基础
1. 什么是算法
算法是完成特定任务的有限指令集。所有的算法必须满足下面的标准:
编辑源文件
能够提共管理程序开发的所有步骤,包括编辑的程序成为集成开发环境(integrated development evironments, IDE)。在windows系统下,使用较为广泛的有Microsoft Visual C++、Dev-Cpp等,在UNIX系统下,有Vim、emacs、eclipes等。这些程序都能提供一个较好的开发平台,使我们能够方便的开发一个程序,接下我们所要了解的都是标准C++,所有源代码都在Dev-cpp下编写,能够编译通过。

16个ACM经典算法介绍

16个ACM经典算法介绍

16个ACM经典算法介绍1.深度优先(DFS)DFS是一种递归的算法,用于遍历或图、树或状态空间。

它从起始节点开始遍历,然后沿着一条路径一直遍历到最深处,然后回溯到上一个节点,继续遍历其他路径。

2.广度优先(BFS)BFS也是一种遍历算法,但与DFS不同的是,它先遍历当前节点的所有相邻节点,然后再遍历相邻节点的相邻节点,以此类推。

BFS通常使用队列数据结构,先进先出。

3. 迪杰斯特拉算法 (Dijkstra's Algorithm)迪杰斯特拉算法用于求解带权图中的最短路径问题。

它采用贪心策略,每次选择当前节点到其他节点的最短路径,从起始节点开始逐步扩展,直到到达目标节点。

4. 弗洛伊德算法 (Floyd's Algorithm)弗洛伊德算法用于求解图中所有节点之间的最短路径。

它采用动态规划的思想,通过不断更新节点之间的最短路径,最终求得所有节点之间的最短路径。

5. 快速排序 (Quick Sort)快速排序是一种高效的排序算法,它通过选择一个基准元素,将待排序列表划分为左右两部分,左边部分都小于基准元素,右边部分都大于基准元素,然后对左右两部分分别递归地进行排序。

6. 归并排序 (Merge Sort)归并排序是一种稳定的排序算法,它将待排序列表分成长度相等的两部分,然后分别对这两部分进行排序,最后将排序好的两部分再合并成一个有序列表。

7. 堆排序 (Heap Sort)堆排序利用二叉堆数据结构实现,它将待排序列表看作是一颗完全二叉树,利用堆的性质对其进行排序。

8. Prim算法 (Prim's Algorithm)Prim算法用于求解最小生成树问题,它从一个节点开始,然后逐步扩展,每次选择当前节点到其他节点的最小权值边,直到生成一棵包含所有节点的树。

9. Kruskal算法 (Kruskal's Algorithm)Kruskal算法也用于求解最小生成树问题,它通过对所有边按权重从小到大进行排序,然后逐步加入图中,直到生成一棵包含所有节点的树。

ACM培训材料PPT课件

ACM培训材料PPT课件

}
2020/10/13
7
注意上面程序的M的好处
上面M定义为10000,这样不仅提高了效率而 且也节省了空间
如果要你把N阶乘转成2或3进制你会吗? 如:把18!转换成2进制. 如果你不会,那么你还没对那个程序M深刻
理解.
2020/10/13
8
N!末尾有多少个0
很简单,只要N!有多少个5这个因子,就有多少 个0.
进位e=0 (e=(a[1]+b[1]+e)/10) c[2]=(a[2]+b[2])%10+e=0, 百位进位e=1,依次下去,
最后把数组输出就是结果(要倒过来输出)
2020/10/13
4
对上面例子的实现
#include<stdio.h>
#include<string.h>
#define N
{
p=a[i]+b[i]+e;
c[i]=p%10;
e=p/10;
}
lc=lb;
while(e>0)
{
lc++;
c[lc]=e%10;
e/=10;
}
for(i=lc;i>=0;i--)
{
printf("%d",c[i]);
}
printf("\n");
return 0;
}
2020/10/13
5
用高精度算N阶乘
汇报人:XXXX 日期:20XX年XX月XX日
11
详细见课堂分析.
2020/10/13
9
fjnu:1743 fjnu:1185 fjnu:1307 fjnu:1191 fjnu:1158

ACM必须掌握的算法

ACM必须掌握的算法

ACM必须的算法1.最短路(Floyd、Dijstra,BellmanFord)2.最小生成树(先写个prim,kruscal要用并查集,不好写)3.大数(高精度)加减乘除4.二分查找. (代码可在五行以内)5.叉乘、判线段相交、然后写个凸包.6.BFS、DFS,同时熟练hash表(要熟,要灵活,代码要简)7.数学上的有:辗转相除(两行内),线段交点、多角形面积公式.8. 调用系统的qsort, 技巧很多,慢慢掌握.9. 任意进制间的转换第二阶段:练习复杂一点,但也较常用的算法。

:1. 二分图匹配(匈牙利),最小路径覆盖2. 网络流,最小费用流。

3. 线段树.4. 并查集。

5. 熟悉动态规划的各个典型:LCS、最长递增子串、三角剖分、记忆化dp6.博弈类算法。

博弈树,二进制法等。

7.最大团,最大独立集。

8.判断点在多边形内。

9. 差分约束系统. 10. 双向广度搜索、A*算法,最小耗散优先.相关的知识图论:路径问题 0/1边权最短路径 BFS 非负边权最短路径(Dijkstra)可以用Dijkstra解决问题的特征负边权最短路径Bellman-Ford Bellman-Ford的Yen-氏优化差分约束系统 Floyd 广义路径问题传递闭包极小极大距离 / 极大极小距离 EulerPath / Tour 圈套圈算法混合图的 Euler Path / TourHamilton Path / Tour 特殊图的Hamilton Path / Tour 构造生成树问题最小生成树第k小生成树最优比率生成树 0/1分数规划度限制生成树连通性问题强大的DFS算法无向图连通性割点割边二连通分支有向图连通性强连通分支 2-SAT最小点基有向无环图拓扑排序有向无环图与动态规划的关系二分图匹配问题一般图问题与二分图问题的转换思路最大匹配有向图的最小路径覆盖0 / 1矩阵的最小覆盖完备匹配最优匹配稳定婚姻网络流问题网络流模型的简单特征和与线性规划的关系最大流最小割定理最大流问题有上下界的最大流问题循环流最小费用最大流 / 最大费用最大流弦图的性质和判定组合数学解决组合数学问题时常用的思想逼近递推 / 动态规划概率问题Polya定理计算几何 / 解析几何计算几何的核心:叉积 / 面积解析几何的主力:复数基本形点直线,线段多边形凸多边形 / 凸包凸包算法的引进,卷包裹法Graham扫描法水平序的引进,共线凸包的补丁完美凸包算法相关判定两直线相交两线段相交点在任意多边形内的判定点在凸多边形内的判定经典问题最小外接圆近似O(n)的最小外接圆算法点集直径旋转卡壳,对踵点多边形的三角剖分数学 / 数论最大公约数Euclid算法扩展的Euclid算法同余方程 / 二元一次不定方程同余方程组线性方程组高斯消元法解mod 2域上的线性方程组整系数方程组的精确解法矩阵行列式的计算利用矩阵乘法快速计算递推关系分数分数树连分数逼近数论计算求N的约数个数求phi(N)求约数和快速数论变换……素数问题概率判素算法概率因子分解数据结构组织结构二叉堆左偏树二项树胜者树跳跃表样式图标斜堆reap统计结构树状数组虚二叉树线段树矩形面积并圆形面积并关系结构Hash表并查集路径压缩思想的应用 STL中的数据结构vectordequeset / map动态规划 / 记忆化搜索动态规划和记忆化搜索在思考方式上的区别最长子序列系列问题最长不下降子序列最长公共子序列最长公共不下降子序列一类NP问题的动态规划解法树型动态规划背包问题动态规划的优化四边形不等式函数的凸凹性状态设计规划方向线性规划常用思想二分最小表示法串KMPTrie结构后缀树/后缀数组 LCA/RMQ有限状态自动机理论排序选择/冒泡快速排序堆排序归并排序基数排序拓扑排序排序网络中级:一.基本算法:(1)C++的标准模版库的应用. (poj3096,poj3007)(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)二.图算法:(1)差分约束系统的建立和求解. (poj1201,poj2983)(2)最小费用最大流(poj2516,poj2516,poj2195)(3)双连通分量(poj2942)(4)强连通分支及其缩点.(poj2186)(5)图的割边和割点(poj3352)(6)最小割模型、网络流规约(poj3308, )三.数据结构.(1)线段树. (poj2528,poj2828,poj2777,poj2886,poj2750)(2)静态二叉检索树. (poj2482,poj2352)(3)树状树组(poj1195,poj3321)(4)RMQ. (poj3264,poj3368)(5)并查集的高级应用. (poj1703,2492)(6)KMP算法. (poj1961,poj2406)四.搜索(1)最优化剪枝和可行性剪枝(2)搜索的技巧和优化 (poj3411,poj1724)(3)记忆化搜索(poj3373,poj1691)五.动态规划(1)较为复杂的动态规划(如动态规划解特别的施行商问题等)(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)(2)记录状态的动态规划. (POJ3254,poj2411,poj1185)(3)树型动态规划(poj2057,poj1947,poj2486,poj3140)六.数学(1)组合数学:1.容斥原理.2.抽屉原理.3.置换群与Polya定理(poj1286,poj2409,poj3270,poj1026).4.递推关系和母函数.(2)数学.1.高斯消元法(poj2947,poj1487,poj2065,poj1166,poj1222)2.概率问题. (poj3071,poj3440)3.GCD、扩展的欧几里德(中国剩余定理) (poj3101)(3)计算方法.1.0/1分数规划. (poj2976)2.三分法求解单峰(单谷)的极值.3.矩阵法(poj3150,poj3422,poj3070)4.迭代逼近(poj3301)(4)随机化算法(poj3318,poj2454)(5)杂题.(poj1870,poj3296,poj3286,poj1095)七.计算几何学.(1)坐标离散化.(2)扫描线算法(例如求矩形的面积和周长并,常和线段树或堆一起使用).(poj1765,poj1177,poj1151,poj3277,po j2280,poj3004)(3)多边形的内核(半平面交)(poj3130,poj3335)(4)几何工具的综合应用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)高级:一.基本算法要求:(1)代码快速写成,精简但不失风格(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)(2)保证正确性和高效性. poj3434二.图算法:(1)度限制最小生成树和第K最短路. (poj1639)(2)最短路,最小生成树,二分图,最大流问题的相关理论(主要是模型建立和求解)(poj3155,poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446(3)最优比率生成树. (poj2728)(4)最小树形图(poj3164)(5)次小生成树.(6)无向图、有向图的最小环三.数据结构.(1)trie图的建立和应用. (poj2778)(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和在线算法(RMQ+dfs)).(poj1330)(3)双端队列和它的应用(维护一个单调的队列,常常在动态规划中起到优化状态转移的目的). (poj2823)(4)左偏树(可合并堆).(5)后缀树(非常有用的数据结构,也是赛区考题的热点).(poj3415,poj3294)四.搜索(1)较麻烦的搜索题目训练(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)(2)广搜的状态优化:利用M进制数存储状态、转化为串用hash表判重、按位压缩存储状态、双向广搜、A*算法.(poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)(3)深搜的优化:尽量用位运算、一定要加剪枝、函数参数尽可能少、层数不易过大、可以考虑双向搜索或者是轮换搜索、IDA*算法. (poj3131,poj2870,poj2286)五.动态规划(1)需要用数据结构优化的动态规划.(poj2754,poj3378,poj3017)(2)四边形不等式理论.(3)较难的状态DP(poj3133)六.数学(1)组合数学.1.MoBius反演(poj2888,poj2154)2.偏序关系理论.(2)博奕论.1.极大极小过程(poj3317,poj1085)2.Nim问题.七.计算几何学.(1)半平面求交(poj3384,poj2540)(2)可视图的建立(poj2966)(3)点集最小圆覆盖.(4)对踵点(poj2079)八.综合题.(poj3109,poj1478,poj1462,poj2729,poj2048,poj333 6,poj3315,poj2148,poj1263)初期:一.基本算法:(1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586)(3)递归和分治法. (4)递推.(5)构造法.(poj3295) (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法:(1)图的深度优先遍历和广度优先遍历.(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)(poj1860,poj3259,poj1062,poj2253,poj1125,po j2240)(3)最小生成树算法(prim,kruskal)(poj1789,poj2485,poj1258,poj3026)(4)拓扑排序 (poj1094)(5)二分图的最大匹配 (匈牙利算法) (poj3041,poj3020)(6)最大流的增广路算法(KM算法). (poj1459,poj3436)三.数据结构.(1)串 (poj1035,poj3080,poj1936)(2)排序(快排、归并排(与逆序数有关)、堆排)(poj2388,poj2299)(3)简单并查集的应用.(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)(poj3349,poj3274,POJ2151,poj1840,poj2002,po j2503)(5)哈夫曼树(poj3253)(6)堆(7)trie树(静态建树、动态建树) (poj2513)四.简单搜索(1)深度优先搜索(poj2488,poj3083,poj3009,poj1321,poj2251)(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)五.动态规划(1)背包问题. (poj1837,poj1276)(2)型如下表的简单DP(可参考lrj的书 page149):1.E[j]=opt{D+w(i,j)}(poj3267,poj1836,poj1260,poj2533)2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1 ]+zij} (最长公共子序列)(poj3176,poj1080,poj1159)3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)六.数学(1)组合数学:1.加法原理和乘法原理.2.排列组合.3.递推关系.(POJ3252,poj1850,poj1019,poj1942)(2)数论.1.素数与整除问题2.进制位.3.同余模运算.(poj2635, poj3292,poj1845,poj2115)(3)计算方法.1.二分法求解单调函数相关知识.(poj3273,poj3258,poj1905,poj3122)七.计算几何学.(1)几何公式.(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)(poj1408,poj1584)(4)凸包. (poj2187,poj1113)。

ACM常用算法模板

ACM常用算法模板

专用模板目录:一、图论1.最大团2.拓扑排序3.最短路和次短路4.SAP模板5.已知各点度,问能否组成一个简单图6.KRUSKAL7. Prim算法求最小生成树8. Dijkstra9 . Bellman-ford10. SPFA11. Kosaraju 模板12. tarjan 模板二、数学1. 剩余定理2. N!中质因子P的个数3.拓展欧几里得4.三角形的各中心到顶点的距离和5.三角形外接圆半径周长6.归并排序求逆序数7. 求N!的位数8.欧拉函数9. Miller-Rabin,大整数分解,求欧拉函数10. 第一类斯特林数11.计算表达式12.约瑟夫问题13.高斯消元法14. Baby-step,giant-step n是素数.n任意15. a^b%c=a ^(b%eular(c)+eular(c)) % c16.判断第二类斯特林数的奇偶性17.求组合数C(n,r)18.进制转换19.Ronberg算法计算积分20.行列式计算21. 返回x 的二进制表示中从低到高的第i位22.高精度运算 +-*/23.超级素数筛选三、数据结构1.树状数组2.线段树求区间的最大、小值3.线段树求区间和4.单调队列5.KMP模板6. 划分树,求区间第k小数7.最大堆,最小堆模板8. RMQ模板求区间最大、最小值9.快速排序,归并排序求逆序数.10.拓展KMP四、计算几何1.凸包面积2.Pick公式求三角形内部有多少点3.多边形边上内部各多少点以及面积pick4.平面最远点对5.判断矩形是否在矩形内6.判断点是否在多边形内7.判断4个点(三维)是否共面8.凸包周长9.等周定理变形一直两端点和周长求最大面积10.平面最近点对11.单位圆最多覆盖多少点(包括边上)12.多边形费马点求点到多边形各个点的最短距离13.矩形并周长14.zoj 2500 求两球体积并一、图论1.最大团#include<iostream>#include<algorithm>using namespace std;int n,m;int cn;//当前顶点数int best;//当前最大顶点数int vis[50];//当前解int bestn[50];//最优解int map[50][50];//临界表void dfs(int i){if(i>n){for(int j=1;j<=n;j++) bestn[j]=vis[j];best=cn;return ;}int ok=1;for(int j=1;j<i;j++){if(vis[j]==1&&map[i][j]==0){ok=0;break;}}if(ok){//进入左子树vis[i]=1;cn++;dfs(i+1);cn--;}if(cn+n-i>best){//进入右子树vis[i]=0;dfs(i+1);}}int main(){while(scanf("%d%d",&n,&m)==2){memset(vis,0,sizeof(vis));memset(map,0,sizeof(map));while(m--){int p,q;scanf("%d%d",&p,&q);map[p][q]=map[q][p]=1;//无向图}cn=0;best=0;dfs(1);printf("%d\n",best);}return 0;}2.拓扑排序#include<iostream>#include<cstring>using namespace std;int map[105][105],in[105],vis[105],ans[105],n;int flag;void dfs(int step){if(flag) return ;if(step==n+1) {flag=1; printf("%d",ans[1]);for(int i=2;i<=n;i++) printf(" %d",ans[i]);printf("\n");return ;}for(int i=1;i<=n;i++){if(vis[i]==0&&in[i]==0){vis[i]=1;for(int j=1;j<=n;j++){if(map[i][j]>0){map[i][j]=-map[i][j];in[j]--;}}ans[step]=i;dfs(step+1);vis[i]=0;for(int j=1;j<=n;j++){if(map[i][j]<0){map[i][j]=-map[i][j];in[j]++;}}}}}int main(){while(scanf("%d",&n)==1){flag=0;memset(map,0,sizeof(map));memset(vis,0,sizeof(vis));memset(in,0,sizeof(in));for(int i=1;i<=n;i++){int t;while(scanf("%d",&t),t){map[i][t]=1;in[t]++;}}dfs(1);}return 0;}3.最短路和次短路#include<iostream>#include<cstdio>#include<vector>#include<cstring>using namespace std;class Node{public:int e,w;//表示终点和边权};const int inf=(1<<25);int main(){int ci;cin>>ci;while(ci--){vector<Node> G[1005];//用邻接表存边int n,m;cin>>n>>m;for(int i=1;i<=m;i++){Node q;int u;cin>>u>>q.e>>q.w;G[u].push_back(q);}int s,f;//起点和终点cin>>s>>f;//dijkstra 求最短路和次短路int flag[1005][2];int dis[1005][2],cnt[1005][2];//0表示最短路,1表示次短路memset(flag,0,sizeof(flag));for(int i=1;i<=n;i++) dis[i][0]=dis[i][1]=inf;dis[s][0]=0;cnt[s][0]=1;//初始化for(int c=0;c<2*n;c++) //找最短路和次短路,故要进行2*n次循环也可以改成while(1){int temp=inf,u=-1,k;//找s-S'集合中的最短路径,u记录点的序号,k记录是最短路或者是次短路for(int j=1;j<=n;j++){if(flag[j][0]==0&&temp>dis[j][0]) temp=dis[j][0],u=j,k=0;else if(flag[j][1]==0&&temp>dis[j][1]) temp=dis[j][1],u=j,k=1;}if(temp==inf) break;//S'集合为空或者不联通,算法结束//更新路径flag[u][k]=1;for(int l=0;l<G[u].size();l++){int d=dis[u][k]+G[u][l].w,j=G[u][l].e;//important//4种情况if(d<dis[j][0]){dis[j][1]=dis[j][0];cnt[j][1]=cnt[j][0];dis[j][0]=d;cnt[j][0]=cnt[u][k];}else if(d==dis[j][0]){cnt[j][0]+=cnt[u][k];}else if(d<dis[j][1]){dis[j][1]=d;cnt[j][1]=cnt[u][k];}else if(d==dis[j][1]){cnt[j][1]+=cnt[u][k];}}}int num=cnt[f][0];//最短路int cc=cnt[f][1];//次短路}return 0;}4.SAP模板#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int inf=(1<<31)-1;const int point_num=300;int cap[point_num][point_num],dist[point_num],gap[point_num];//初始化见main里面int s0,t0,n;//源,汇和点数int find_path(int p,int limit=0x3f3f3f3f){if(p==t0) return limit;for(int i=0;i<n;i++)if(dist[p]==dist[i]+1 && cap[p][i]>0){int t=find_path(i,min(cap[p][i],limit));if(t<0) return t;if(t>0){cap[p][i]-=t;cap[i][p]+=t;return t;}}int label=n;for(int i=0;i<n;i++) if(cap[p][i]>0) label=min(label,dist[i]+1);if(--gap[dist[p]]==0 || dist[s0]>=n ) return -1;++gap[dist[p]=label];return 0;}int sap(){//初始化s,ts0=0,t0=n-1;int t=0,maxflow=0;gap[0]=n;while((t=find_path(s0))>=0) maxflow+=t;return maxflow;}int main(){int ci;while(cin>>ci>>n){//初始化memset(cap,0,sizeof(cap));memset(dist,0,sizeof(dist));memset(gap,0,sizeof(gap));//初始化capwhile(ci--){int x,y,c;cin>>x>>y>>c;x--;y--;cap[x][y]+=c;//因题而异}int ans=sap();cout<<ans<<endl;}return 0;}5.已知各点度,问能否组成一个简单图#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int inf=(1<<30);int d[1100];bool cmp(int x,int y){return x>y;}int main(){int ci;scanf("%d",&ci);while(ci--){int n,flag=1,cnt=0;scanf("%d",&n); for(int i=0;i<n;i++){scanf("%d",&d[i]);if(d[i]>n-1||d[i]<=0) flag=0; cnt+=d[i];}if(flag==0||cnt%2){printf("no\n");continue;}sort(d,d+n,cmp);for(int l=n;l>0;l--){for(int i=1;i<l&&d[0];i++){d[0]--,d[i]--;if(d[i]<0){flag=0;break;}}if(d[0]) flag=0;if(flag==0) break;d[0]=-inf;sort(d,d+l,cmp);}if(flag) printf("yes\n");else printf("no\n");}return 0;}6.KRUSKAL#include<iostream>#include<algorithm>using namespace std;int u[15005],v[15005],w[15005],fath[15005],r[15005];int ans1[15005],ans2[15005];bool cmp(int i,int j){return w[i]<w[j];}int find(int x){return fath[x]==x?x:fath[x]=find(fath[x]);}int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++) fath[i]=i;for(int i=1;i<=m;i++) r[i]=i;for(int i=1;i<=m;i++){cin>>u[i]>>v[i]>>w[i];}sort(r+1,r+m+1,cmp);int maxn=0,ans=0,k=0;for(int i=1;i<=m;i++){int e=r[i];int x=find(u[e]),y=find(v[e]);if(x!=y){ans+=w[e];fath[x]=y;if(w[e]>maxn) maxn=w[e];ans1[k]=u[e];ans2[k++]=v[e];}}return 0;}7.prime求最小生成树语法:prim(Graph G,int vcount,int father[]);参数:G:图,用邻接矩阵表示vcount:表示图的顶点个数father[]:用来记录每个节点的父节点返回值:null注意:常数max_vertexes 为图最大节点数常数infinity为无穷大源程序:#define infinity 1000000#define max_vertexes 5typedef int Graph[max_vertexes][max_vertexes];void prim(Graph G,int vcount,int father[]){int i,j,k;intlowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes]; for (i=0;i<vcount;i++){lowcost[i]=G[0][i];closeset[i]=0;used[i]=0;father[i]=-1;}used[0]=1;for (i=1;i<vcount;i++){j=0;while (used[j]) j++;for (k=0;k<vcount;k++)if ((!used[k])&&(lowcost[k]<lowcost[j])) j=k;father[j]=closeset[j];used[j]=1;for (k=0;k<vcount;k++)if (!used[k]&&(G[j][k]<lowcost[k])){ lowcost[k]=G[j][k];closeset[k]=j; }}}8.Dijkstra语法:result=Dijkstra(Graph G,int n,int s,int t, int path[]); 参数:G:图,用邻接矩阵表示n:图的顶点个数s:开始节点t:目标节点path[]:用于返回由开始节点到目标节点的路径返回值:最短路径长度注意:输入的图的权必须非负顶点标号从0 开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Dijkstra(Graph G,int n,int s,int t, int path[]){int i,j,w,minc,d[max_vertexes],mark[max_vertexes];for (i=0;i<n;i++) mark[i]=0;for (i=0;i<n;i++){ d[i]=G[s][i];path[i]=s; }mark[s]=1;path[s]=0;d[s]=0;for (i=1;i<n;i++){minc=infinity;w=0;for (j=0;j<n;j++)if ((mark[j]==0)&&(minc>=d[j])) {minc=d[j];w=j;}mark[w]=1;for (j=0;j<n;j++)if((mark[j]==0)&&(G[w][j]!=infinity)&&(d[j]>d[w]+G[w][j])){ d[j]=d[w]+G[w][j];path[j]=w; }}return d[t];}9.Bellman-ford语法:result=Bellman_ford(Graph G,int n,int s,int t,int path[],int success);参数:G:图,用邻接矩阵表示n:图的顶点个数s:开始节点t:目标节点path[]:用于返回由开始节点到目标节点的路径success:函数是否执行成功返回值:最短路径长度注意:输入的图的权可以为负,如果存在一个从源点可达的权为负的回路则success=0顶点标号从0 开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Bellman_ford(Graph G,int n,int s,int t,int path[],int success){int i,j,k,d[max_vertexes];for (i=0;i<n;i++) {d[i]=infinity;path[i]=0;}d[s]=0;for (k=1;k<n;k++)for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]){d[j]=d[i]+G[i][j];path[j]=i;}success=0;for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]) return 0;success=1;return d[t];}10. SPFA#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;const __int64 maxn=1001000;const __int64 inf=1000100000;struct edge//邻接表{__int64 t,w;//s->t=w;__int64 next;//数组模拟指针};__int64 p[maxn],pf[maxn];//邻接表头节点edge G[maxn],Gf[maxn];//邻接表__int64 V,E;//点数[1-n] 边数__int64 dis[maxn];__int64 que[maxn],fro,rear;//模拟队列__int64 vis[maxn];__int64 inque[maxn];//入队次数bool spfa(__int64 s0){fro=rear=0;for(__int64 i=1;i<=V;i++) dis[i]=inf;dis[s0]=0;memset(vis,0,sizeof(vis));memset(inque,0,sizeof(inque));que[rear++]=s0;vis[s0]=1;inque[s0]++;while(fro!=rear){__int64 u=que[fro];fro++;if(fro==maxn) fro=0;vis[u]=0;for(__int64 i=p[u];i!=-1;i=G[i].next){__int64 s=u,t=G[i].t,w=G[i].w;if(dis[t]>dis[s]+w){dis[t]=dis[s]+w;if(vis[t]==0){que[rear++]=t,vis[t]=1;inque[t]++;if(inque[t]>V) return false;if(rear==maxn) rear=0;}}}}return true;}int main(){__int64 ci;scanf("%I64d",&ci);while(ci--){scanf("%I64d%I64d",&V,&E);memset(p,-1,sizeof(p));memset(pf,-1,sizeof(pf)); for(__int64 i=0;i<E;i++){__int64 u,v,w;scanf("%I64d%I64d%I64d",&u,&v,&w);G[i].t=v;G[i].w=w;G[i].next=p[u];p[u]=i;Gf[i].t=u;Gf[i].w=w;Gf[i].next=pf[v];pf[v]=i;}__int64 ans=0;spfa(1);//求第一个点到其他点的最短距离和for(__int64 i=1;i<=V;i++) ans+=dis[i];//反方向再来一次spfa 求其他点到第一个点的最短距离和 for(__int64 i=1;i<=V;i++) p[i]=pf[i];for(__int64 i=0;i<E;i++) G[i]=Gf[i];spfa(1);for(__int64 i=1;i<=V;i++) ans+=dis[i];printf("%I64d\n",ans);}return 0;}11.Kosaraju模板#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;struct edge{int t,w;//u->t=w;int next;};int V,E;//点数(从1开始),边数int p[maxn],pf[maxn];//邻接表原图,逆图edge G[maxn],Gf[maxn];//邻接表原图,逆图int l,lf;void init(){memset(p,-1,sizeof(p));memset(pf,-1,sizeof(pf));l=lf=0;}void addedge(int u,int t,int w,int l){G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}void addedgef(int u,int t,int w,int lf){Gf[l].w=w;Gf[l].t=t;Gf[l].next=pf[u];pf[u]=l;}///Kosaraju算法,返回为强连通分量个数bool flag[maxn]; //访问标志数组int belg[maxn]; //存储强连通分量,其中belg[i]表示顶点i属于第belg[i]个强连通分量int numb[maxn]; //结束时间(出栈顺序)标记,其中numb[i]表示离开时间为i的顶点//用于第一次深搜,求得numb[1..n]的值void VisitOne(int cur, int &sig){flag[cur] = true;for (int i=p[cur];i!=-1;i=G[i].next){if (!flag[G[i].t]){VisitOne(G[i].t,sig);}}numb[++sig] = cur;}//用于第二次深搜,求得belg[1..n]的值void VisitTwo(int cur, int sig){flag[cur] = true;belg[cur] = sig;for (int i=pf[cur];i!=-1;i=Gf[i].next){if (!flag[Gf[i].t]){VisitTwo(Gf[i].t,sig);}}//Kosaraju算法,返回为强连通分量个数int Kosaraju_StronglyConnectedComponent(){int i, sig;//第一次深搜memset(flag,0,sizeof(flag));for ( sig=0,i=1; i<=V; ++i ){if ( false==flag[i] ){VisitOne(i,sig);}}//第二次深搜memset(flag,0,sizeof(flag));for ( sig=0,i=V; i>0; --i ){if ( false==flag[numb[i]] ){VisitTwo(numb[i],++sig);}}return sig;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int u=i,t,w=1;while(scanf("%d",&t)==1&&t){E++;addedge(u,t,w,l++);addedgef(t,u,w,lf++);}}int ans=Kosaraju_StronglyConnectedComponent(); printf("%d\n",ans);}return 0;12.tarjan模板//自己模板#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;int V,E;//点数(1) 边数struct edge//邻接表{int t,w;//u->t=w;int next;};int p[maxn];//表头节点edge G[maxn];int l;void init(){memset(p,-1,sizeof(p));l=0;}//添加边void addedge(int u,int t,int w,int l)//u->t=w;{G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}//tarjan算法求有向图强联通分量int dfn[maxn],lowc[maxn];//dfn[u]节点u搜索的次序编号,lowc[u]u或者u的子树能够追溯到的栈中的最早的节点int belg[maxn];//第i个节点属于belg[i]个强连通分量int stck[maxn],stop;//stck栈int instck[maxn];//第i个节点是否在栈中int scnt;//强联通分量int index;void dfs(int i){dfn[i]=lowc[i]=++index;instck[i]=1;//节点i入栈stck[++stop]=i;for(int j=p[i];j!=-1;j=G[j].next){int t=G[j].t;//更新lowc数组if(!dfn[t])//t没有遍历过{dfs(t);if(lowc[i]>lowc[t]) lowc[i]=lowc[t];}//t是i的祖先节点else if(instck[t]&&lowc[i]>dfn[t]) lowc[i]=dfn[t];}//是强连通分量的根节点if(dfn[i]==lowc[i]){scnt++;int t;do{t=stck[stop--];instck[t]=0;belg[t]=scnt;}while(t!=i);}}int tarjan(){stop=scnt=index=0;memset(dfn,0,sizeof(dfn));memset(instck,0,sizeof(instck));for(int i=1;i<=V;i++){if(!dfn[i]) dfs(i);}return scnt;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int x;while(scanf("%d",&x)==1&&x){E++;addedge(i,x,1,l++);}}int ans=tarjan();printf("%d\n",ans);}return 0;}//吉大模板邻接表版#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;int V,E;//点数(1) 边数struct edge//邻接表{int t,w;//u->t=w;int next;};int p[maxn];//表头节点edge G[maxn];int l;void init(){memset(p,-1,sizeof(p));l=0;}//添加边void addedge(int u,int t,int w,int l)//u->t=w;{G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}//tarjan算法求有向图强联通分量int dfn[maxn],lowc[maxn];//dfn[u]节点u搜索的次序编号,lowc[u]u或者u的子树能够追溯到的栈中的最早的节点int stck[maxn],stop;//stck栈int pre[maxn];//int scnt;//强联通分量int cnt;//void dfs(int v)//1-V{int t,minc=lowc[v]=pre[v]=cnt++;stck[stop++]=v;for(int i=p[v];i!=-1;i=G[i].next){int pv=G[i].t;if(pre[pv]==-1) dfs(pv);if(lowc[pv]<minc) minc=lowc[pv]; }if(minc<lowc[v]){lowc[v]=minc;return ;}do{dfn[t=stck[--stop]]=scnt;lowc[t]=V;}while(t!=v);++scnt;}int tarjan(){stop=cnt=scnt=0;memset(pre,-1,sizeof(pre));for(int i=1;i<=V;i++){if(pre[i]==-1) dfs(i);}return scnt;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int x;while(scanf("%d",&x)==1&&x){E++;addedge(i,x,1,l++);}}int ans=tarjan();printf("%d\n",ans);}return 0;}二、数学1.剩余定理int mod(int c[],int b[],int n){int all_multy=1,sum=0;int i,j,x[5];for(i=0;i<n;i++)all_multy*=c[i];for(i=0;i<n;i++)x[i]=all_multy/c[i];for(i=0;i<n;i++){j=1;while((x[i]*j)%c[i]!=1)j++;x[i]*=j;}for(i=0;i<n;i++)sum+=(b[i]*x[i]);return sum%all_multy;}2.N!中质因子P的个数//对于任意质数p,n!中有(n/p+n/p^2+n/p^3+...)个质因子p。

ACM常用算法

ACM常用算法

ACM常用算法ACM常考算法ACM小组内部预定函数Ver 2.0 by IcyFenix数学问题:1.精度计算――大数2.精度计算――乘法(大数3.精度计算――乘法(大阶乘5.精度计算――减法9.快速傅立叶变换(FFT)字符串处理:1.字符串替换计算几何:1.叉乘法求任意多边形面积5.射向法判断点是否在多边形内部9.点到线段最短距离数论:1.x的二进制长度5.求解模线性方程组(中国余数定理) 图论:1.Prim算法求最小生成树排序/查找:1.快速排序数据结构:1.顺序队列乘小数)6.任意进制转换10.Ronberg算法计算积分2.字符串查找2.求三角形面积6.判断点是否在线段上10.求两直线的交点2.返回x的二进制表示中从低到高的第i位6.筛法素数产生器2.Dijkstra算法求单源最短路径2.希尔排序2.顺序栈数乘大数)4.精度计算――加法7.最大公约数、最小公倍数8.组合序列11.行列式计算12.求排列组合数3.字符串截取3.两矢量间角度4.两点距离(2D、3D)7.判断两线段是否相交8.判断线段与直线是否相交11.判断一个封闭图形是12.Graham扫描法寻凹集还是凸集找凸包3.模取幂运算4.求解模线性方程7.判断一个数是否素数3.Bellman-ford算法求4.Floyd算法求每对单源最短路径节点间最短路径3.选择法排序4.二分查找3.链表4.链栈ACM常考算法5.二叉树一、数学问题1.精度计算――大数阶乘语法:int result=factorial(int n); 参数:n:n 的阶乘返回阶乘结果的位数值:注意:源程序:本程序直接输出n!的结果,需要返回结果请保留long a[] 需要math.hint factorial(int n){long a[__];int i,j,l,c,m=0,w; a=1;for(i=1;ii++) { c=0;for(j=0;jj++) {a[j]=a[j]*i+c; c=a[j]/__; a[j]=a[j]%__; }if(c0) {m++;a[m]=c;} }w=m*4+log10(a[m])+1;printf(“\n%ld",a[m]);for(i=m-1;ii--) printf("%4.4ld",a[i]);return w; }2.精度计算――乘法(大数乘小数)语法:mult(char c[],char t[],int m); 参数:c[]:被乘数,用字符串表示,位数不限t[]:结果,用字符串表示m:乘数,限定10以内返回null 值:注意:需要string.hACM常考算法源程序:void mult(char c[],char t[],int m) {int i,l,k,flag,add=0; char s; l=strlen(c);for (i=0;ii++)s[l-i-1]=c[i]-'0';for (i=0;ii++) {k=s[i]*m+add;if (k=10) {s[i]=k%10;add=k/10;flag=1;}else {s[i]=k;flag=0;add=0;} }if (flag) {l=i+1;s[i]=add;}else l=i; for (i=0;ii++)t[l-1-i]=s[i]+'0'; t[l]='\0'; }3.精度计算――乘法(大数乘大数)语法:mult(char a[],char b[],char s[]); 参数:a[]:被乘数,用字符串表示,位数不限b[]:乘数,用字符串表示,位数不限t[]:结果,用字符串表示返回null 值:注意:源程序:空间复杂度为o(n^2) 需要string.hvoid mult(char a[],char b[],char s[]) {int i,j,k=0,alen,blen,sum=0,res={0},flag=0; char result;alen=strlen(a);blen=strlen(b);for (i=0;ialen;i++)for (j=0;jblen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0'); for (i=alen-1;ii--) {for (j=blen-1;jj--) sum=sum+res[i+blen-j-1][j]; result[k]=sum%10; k=k+1;ACM常考算法sum=sum/10; }for (i=blen-2;ii--) {for (j=0;jj++) sum=sum+res[i-j][j]; result[k]=sum%10; k=k+1;sum=sum/10; }if (sum!=0) {result[k]=sum;k=k+1;} for (i=0;ii++) result[i]+='0';for (i=k-1;ii--) s[i]=result[k-1-i]; s[k]='\0';while(1) {if (strlen(s)!=strlen(a)s=='0') strcpy(s,s+1); elsebreak; } }4.精度计算――加法语法:add(char a[],char b[],char s[]); 参数:a[]:被乘数,用字符串表示,位数不限b[]:乘数,用字符串表示,位数不限t[]:结果,用字符串表示返回null 值:注意:源程序:空间复杂度为o(n^2) 需要string.hvoid add(char a[],char b[],char back[]) {int i,j,k,up,x,y,z,l; char *c; if (strlen(a)strlen(b)) l=strlen(a)+2;elsel=strlen(b)+2; c=(char *) malloc(l*sizeof(char)); i=strlen(a)-1; j=strlen(b)-1; k=0;up=0;while(i=0||j=0) {if(i0) x='0'; else x=a[i];ACM常考算法if(j0) y='0'; else y=b[j]; z=x-'0'+y-'0'; if(up) z+=1;if(z9) {up=1;z%=10;} else up=0; c[k++]=z+'0'; i--;j--; }if(up) c[k++]='1'; i=0;c[k]='\0';for(k-=1;kk--) back[i++]=c[k]; back[i]='\0'; }5.精度计算――减法语法:sub(char s1[],char s2[],char t[]); 参数:s1[]:被减数,用字符串表示,位数不限s2[]:减数,用字符串表示,位数不限t[]:结果,用字符串表示返回null 值:注意:源程序:默认s1=s2,程序未处理负数情况需要string.hvoid sub(char s1[],char s2[],char t[]) {int i,l2,l1,k;l2=strlen(s2);l1=strlen(s1); t[l1]='\0';l1--;for (i=l2-1;ii--,l1--) {if (s1[l1]-s2[i]=0)t[l1]=s1[l1]-s2[i]+'0'; else {t[l1]=10+s1[l1]-s2[i]+'0'; s1[l1-1]=s1[l1-1]-1; } } k=l1;while(s1[k]0) {s1[k]+=10;s1[k-1]-=1;k--;} while(l1=0) {t[l1]=s1[l1];l1--;} loop:if (t=='0') {ACM常考算法l1=strlen(s1);for (i=0;il1-1;i++) t[i]=t[i+1]; t[l1-1]='\0'; goto loop; }if (strlen(t)==0) {t='0';t='\0';} }6.任意进制转换语法:conversion(char s1[],char s2[],long d1,long d2); 参数:s[]:原进制数字,用字符串表示s2[]:转换结果,用字符串表示d1:原进制数d2:需要转换到的进制数返回null 值:注意:源程序:高于9的位数用大写'A'~'Z'表示,2~16位进制通过验证void conversion(char s[],char s2[],long d1,long d2) {long i,j,t,num; char c; num=0;for (i=0;s[i]!='\0';i++) {if (s[i]='9's[i]='0') t=s[i]-'0';else t=s[i]-'A'+10;num=num*d1+t; } i=0; while(1) {t=num%d2;if (t=9) s2[i]=t+'0';else s2[i]=t+'A'-10; num/=d2;if (num==0)break; i++; }for (j=0;jj++){c=s2[j];s2[j]=s[i-j];s2[i-j]=c;} s2[i+1]='\0'; }7.最大公约数、最小公倍数ACM常考算法语法:resulet=hcf(int a,int b)、result=lcd(int a,int b) 参数:a:int a,求最大公约数或最小公倍数b:int b,求最大公约数或最小公倍数返回返回最大公约数(hcf)或最小公倍数(lcd)值:注意:源程序:lcd 需要连同hcf 使用int hcf(int a,int b) {int r=0; while(b!=0) {r=a%b; a=b; b=r; }return(a); }lcd(int u,int v,int h) {return(u*v/h); }8.组合序列语法:m_of_n(int m,int n1,int m1,int* a,int head) 参数:m:组合数C的上参数n1:组合数C的下参数m1:组合数C的上参数,递归之用*a:1~n的整数序列数组head:头指针返回null 值:注意:源程序:*a需要自行产生初始调用时,m=m1、head=0调用例子:求C(m,n)序列:m_of_n(m,n,m,a,0);ACM常考算法void m_of_n(int m,int n1,int m1,int* a,int head) {int i,t;if(m10 || m1n1)return; if(m1==n1) {for(i=0;ii++) couta[i]' '; // 输出序列cout'\n'; return; }m_of_n(m,n1-1,m1,a,head); // 递归调用t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t; m_of_n(m,n1-1,m1-1,a,head+1); // 再次递归调用t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t; }9.快速傅立叶变换(FFT)语法:kkfft(double pr[],double pi[],int n,int k,double fr[],double fi[],int l,int il); 参数:pr[n]:输入的实部pi[n]:数入的虚部n,k:满足n=2^k fr[n]:输出的实部fi[n]:输出的虚部l:逻辑开关,0 FFT,1 ifFTil:逻辑开关,0 输出按实部/虚部;1 输出按模/幅角返回null 值:注意:源程序:需要math.hvoid kkfft(pr,pi,n,k,fr,fi,l,il)int n,k,l,il;double pr[],pi[],fr[],fi[]; {int it,m,is,i,j,nv,l0;double p,q,s,vr,vi,poddr,poddi; for (it=0; it=n-1; it++) {m=it; is=0;for (i=0; i=k-1; i++){j=m/2; is=2*is+(m-2*j); m=j;} fr[it]=pr[is]; fi[it]=pi[is]; }pr=1.0; pi=0.0; p=6.__-__6/(1.0*n);pr=cos(p); pi=-sin(p);ACM常考算法if (l!=0) pi=-pi; for (i=2; i=n-1; i++) {p=pr[i-1]*pr; q=pi[i-1]*pi;s=(pr[i-1]+pi[i-1])*(pr+pi); pr[i]=p-q; pi[i]=s-p-q; }for (it=0; it=n-2; it=it+2) {vr=fr[it]; vi=fi[it];fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1]; }m=n/2; nv=2;for (l0=k-2; l0 l0--) {m=m/2; nv=2*nv;for (it=0; it=(m-1)*nv; it=it+nv) for (j=0; j=(nv/2)-1; j++) {p=pr[m*j]*fr[it+j+nv/2]; q=pi[m*j]*fi[it+j+nv/2]; s=pr[m*j]+pi[m*j];s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]); poddr=p-q; poddi=s-p-q;fr[it+j+nv/2]=fr[it+j]-poddr; fi[it+j+nv/2]=fi[it+j]-poddi;fr[it+j]=fr[it+j]+poddr; fi[it+j]=fi[it+j]+poddi; } }if (l!=0)for (i=0; i=n-1; i++) {fr[i]=fr[i]/(1.0*n); fi[i]=fi[i]/(1.0*n); } if (il!=0)for (i=0; i=n-1; i++) {pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]); if (fabs(fr[i])0.000001*fabs(fi[i])) {if ((fi[i]*fr[i])0) pi[i]=90.0; else pi[i]=-90.0; } elsepi[i]=atan(fi[i]/fr[i])*360.0/6.__-__6; } return; }10.Ronberg算法计算积分语法:result=integral(double a,double b);ACM常考算法参数:a:积分上限b:积分下限function积分函数f:返回值:f在(a,b)之间的积分值注意:源程序:function f(x)需要自行修改,程序中用的是sina(x)/x 需要math.h 默认精度要求是1e-5double f(double x) {return sin(x)/x; //在这里插入被积函数}double integral(double a,double b) {double h=b-a;double t1=(1+f(b))*h/2.0; int k=1;double r1,r2,s1,s2,c1,c2,t2; loop:double s=0.0;double x=a+h/2.0; while(xb) {s+=f(x); x+=h; }t2=(t1+h*s)/2.0; s2=t2+(t2-t1)/3.0; if(k==1) {k++;h/=2.0;t1=t2;s1=s2; goto loop; }c2=s2+(s2-s1)/15.0; if(k==2){c1=c2;k++;h/=2.0; t1=t2;s1=s2; goto loop; }r2=c2+(c2-c1)/63.0; if(k==3){r1=r2; c1=c2;k++; h/=2.0;t1=t2;s1=s2; goto loop; }while(fabs(1-r1/r2)1e-5){ r1=r2;c1=c2;k++; h/=2.0;ACM常考算法t1=t2;s1=s2; goto loop; }return r2; }11.行列式计算语法:result=js(int s[][],int n) 参数:s[][]:行列式存储数组n:行列式维数,递归用返回行列式值值:注意:源程序:函数中常数N为行列式维度,需自行定义int js(s,n)int s[][N],n; {int z,j,k,r,total=0; int b[N][N];/*b[N][N]用于存放,在矩阵s[N][N]中元素s的余子式*/if(n2) {for(z=0;zz++) {for(j=0;jj++)for(k=0;kk++)if(k=z) b[j][k]=s[j+1][k+1]; else b[j][k]=s[j+1][k];if(z%2==0) r=s[z]*js(b,n-1); /*递归调用*/ else r=(-1)*s[z]*js(b,n-1); total=total+r; } }else if(n==2)total=s*s-s*s; return total; }12.求排列组合数语法:result=P(long n,long m); / result=long C(long n,long m); 参数:m:排列组合的上系数n:排列组合的下系数返回排列组合数ACM常考算法值:注意:源程序:符合数学规则:m=nlong P(long n,long m) {long p=1; while(m!=0){p*=n;n--;m--;} return p; }long C(long n,long m) {long i,c=1; i=m;while(i!=0){c*=n;n--;i--;} while(m!=0) {c/=m;m--;} return c; }二、字符串处理1.字符串替换语法:replace(char str[],char key[],char swap[]); 参数:str[]:在此源字符串进行替换操作key[]:被替换的字符串,不能为空串swap[]替换的字符串,可以为空串,为空串表示在源字符中删除key[] :返回null 值:注意:源程序:默认str[]长度小于1000,如否,重新设定设定tmp大小需要string.hvoid replace(char str[],char key[],char swap[]) {int l1,l2,l3,i,j,flag; char tmp; l1=strlen(str); l2=strlen(key);l3=strlen(swap);for (i=0;i=l1-l2;i++)ACM常考算法{flag=1;for (j=0;jj++)if (str[i+j]!=key[j]) {flag=0;break;} if (flag) {strcpy(tmp,str);strcpy(tmp[i],swap);strcpy(tmp[i+l3],str[i+l2]); strcpy(str,tmp); i+=l3-1;l1=strlen(str); } } }2.字符串查找语法:result=strfind(char str[],char key[]); 参数:str[]:在此源字符串进行查找操作key[]:被查找的字符串,不能为空串返回如果查找成功,返回key在str中第一次出现的位置,否则返回-1 值:注意:源程序:需要string.hint strfind(char str[],char key[]) {int l1,l2,i,j,flag; l1=strlen(str); l2=strlen(key);for (i=0;i=l1-l2;i++) {flag=1;for (j=0;jj++)if (str[i+j]!=key[j]) {flag=0;break;} if (flag)return i; }return -1; }3.字符串截取语法:mid(char str[],int start,int len,char strback[]) 参数:str[]:操作的目标字符串start:从第start个字符串开始,截取长度为len的字符ACM常考算法len:从第start个字符串开始,截取长度为len的字符strback[ 截取的到的字符]:返回值:0:超出字符串长度,截取失败;1:截取成功注意:需要string.h源程序:int mid(char str[],int start,int len,char strback[]) {int l,i,k=0; l=strlen(str);if (start+lenl)return 0; for (i=start;istart+len;i++) strback[k++]=str[i]; strback[k]='\0'; return 1; }三、计算几何1.叉乘法求任意多边形面积语法:result=polygonarea(Point *polygon,int N); 参数:*polyg多变形顶点数组on:N:多边形顶点数目返回多边形面积值:注意:源程序:支持任意多边形,凹、凸皆可多边形顶点输入时按顺时针顺序排列typedef struct { double x,y; } Point;double polygonarea(Point *polygon,int N) {int i,j;double area = 0;for (i=0;ii++) { j = (i + 1) % N;area += polygon[i].x * polygon[j].y; area -= polygon[i].y *polygon[j].x; }ACM常考算法area /= 2;return(area 0 ? -area : area); }2.求三角形面积语法:result=area3(float x1,float y1,float x2,float y2,float x3,float y3); 参数:x1~3:三角形3个顶点x坐标y1~3:三角形3个顶点y坐标返回三角形面积值:注意:源程序:需要math.hfloat area3(float x1,float y1,float x2,float y2,float x3,float y3) {float a,b,c,p,s;a=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); b=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3)); c=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)); p=(a+b+c)/2;s=sqrt(p*(p-a)*(p-b)*(p-c)); return s; }3.两矢量间角度语法:result=angle(double x1,double y1,double x2,double y2); 参数:x/y1~两矢量的坐标2:返回两的角度矢量值:注意:源程序:返回角度为弧度制,并且以逆时针方向为正方向需要math.h#define PI 3.__-__double angle(double x1,double y1,double x2,double y2) {ACM常考算法double dtheta,theta1,theta2; theta1 = atan2(y1,x1); theta2 =atan2(y2,x2); dtheta = theta2 - theta1; while (dtheta PI) dtheta -= PI*2; while (dtheta -PI) dtheta += PI*2; return(dtheta); }4.两点距离(2D、3D)语法:result=distance_2d(float x1,float x2,float y1,float y2); 参数:x/y/z1各点的x、y、z坐标~2:返回两点之间的距离值:注意:源程序:需要math.hfloat distance_2d(float x1,float x2,float y1,float y2) {return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))); }float distance_3d(float x1,float x2,float y1,float y2,float z1,float z2) { return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2))); }5.射向法判断点是否在多边形内部语法:result=insidepolygon(Point *polygon,int N,Point p); 参数:*polyg多边形顶点数组on:N:多边形顶点个数p:被判断点返回0:点在多边形内部;1:点在多边形外部值:注意:若p点在多边形顶点或者边上,返回值不确定,需另行判断ACM常考算法源程序:需要math.h#define MIN(x,y) (x y ? x : y)#define MAX(x,y) (x y ? x : y) typedef struct { double x,y; } Point;int insidepolygon(Point *polygon,int N,Point p) {int counter = 0; int i;double xinters; Point p1,p2;p1 = polygon;for (i=1;ii++) { p2 = polygon[i % N];if (p.y MIN(p1.y,p2.y)) {if (p.y = MAX(p1.y,p2.y)) {if (p.x = MAX(p1.x,p2.x)) { if (p1.y != p2.y) { xinters =(p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;if (p1.x == p2.x || p.x = xinters) counter++; } } } }p1 = p2; }if (counter % 2 == 0) return(__); elsereturn(INSIDE); }6.判断点是否在线段上语法:result=Pointonline(Point p1,Point p2,Point p); 参数:p1、p2:线段的两个端点p:被判断点返回0:点在不在线段上;1:点在线段上值:注意:源程若p线段端点上返回1 需要math.hACM常考算法序:#define MIN(x,y) (x y ? x : y)#define MAX(x,y) (x y ? x : y) typedef struct {double x,y; } Point;int FC(double x1,double x2) {if (x1-x20.000002x1-x2-0.000002)return 1;else return 0; }int Pointonline(Point p1,Point p2,Point p) {double x1,y1,x2,y2; x1=p.x-p1.x; x2=p2.x-p1.x; y1=p.y-p1.y; y2=p2.y-p1.y;if (FC(x1*y2-x2*y1,0)==0)return 0;if ((MIN(p1.x,p2.x)=p.xp.x=MAX(p1.x,p2.x))(MIN(p1.y,p2.y)=p.yp.y=MAX(p1.y,p2.y))) return 1;else return 0; }7.判断两线段是否相交语法:result=sectintersect(Point p1,Point p2,Point p3,Point p4); 参数:p1~两条线段的四个端点4:返回0:两线段不相交;1:两线段相交;2两线段首尾相接值:注意:源程序:p1!=p2;p3!=p4;#define MIN(x,y) (x y ? x : y)#define MAX(x,y) (x y ? x : y) typedef struct { double x,y; } Point;int lineintersect(Point p1,Point p2,Point p3,Point p4) {Point tp1,tp2,tp3; if((p1.x==p3.xp1.y==p3.y)||(p1.x==p4.xp1.y==p4.y)||(p2.x==p3.xp2.y==p3.y )||(p2.x==p4.xp2.y==p4.y)) return 2; //快速排斥试验if((MIN(p1.x,p2.x)p3.xp3.xMAX(p1.x,p2.x)MIN(p1.y,p2.y)p3.yMAX(p1.y,p2.y))|| ACM常考算法(MIN(p1.x,p2.x)p4.xp3.xMAX(p1.x,p2.x)MIN(p1.y,p2.y)p3.yMAX(p1.y,p2.y))) ; else return 0;//跨立试验tp1.x=p1.x-p3.x; tp1.y=p1.y-p3.y; tp2.x=p4.x-p3.x; tp2.y=p4.y-p3.y; tp3.x=p2.x-p3.x; tp3.y=p2.y-p3.y;if ((tp1.__tp2.y-tp1.y*tp2.x)*(tp2.__tp3.y-tp2.y*tp3.x)=0)return 1;else return 0; }8.判断线段与直线是否相交语法:result=lineintersect(Point p1,Point p2,Point p3,Point p4); 参数:p1、p2:线段的两个端点p3、p4:直线上的两个点返回0:线段直线不相交;1:线段和直线相交值:注意:源程序:如线段在直线上,返回1typedef struct { double x,y; } Point;int lineintersect(Point p1,Point p2,Point p3,Point p4) {Point tp1,tp2,tp3; tp1.x=p1.x-p3.x; tp1.y=p1.y-p3.y; tp2.x=p4.x-p3.x; tp2.y=p4.y-p3.y; tp3.x=p2.x-p3.x; tp3.y=p2.y-p3.y;if ((tp1.__tp2.y-tp1.y*tp2.x)*(tp2.__tp3.y-tp2.y*tp3.x)=0)return 1;else return 0; }9.点到线段最短距离语法:result=mindistance(Point p1,Point p2,Point q); 参数:p1、线段的两个端点p2:ACM常考算法q:判断点返回点q到线段p1p2的距离值:注意:源程序:需要math.h#define MIN(x,y) (x y ? x : y)#define MAX(x,y) (x y ? x : y) typedef struct { double x,y; } Point;double mindistance(Point p1,Point p2,Point q) {int flag=1; double k; Point s;if (p1.x==p2.x) {s.x=p1.x;s.y=q.y;flag=0;} if (p1.y==p2.y){s.x=q.x;s.y=p1.y;flag=0;} if (flag) {k=(p2.y-p1.y)/(p2.x-p1.x);s.x=(k*k*p1.x+k*(q.y-p1.y)+q.x)/(k*k+1); s.y=k*(s.x-p1.x)+p1.y; }if (MIN(p1.x,p2.x)=s.xs.x=MAX(p1.x,p2.x))return sqrt((q.x-s.x)*(q.x-s.x)+(q.y-s.y)*(q.y-s.y)); elsereturnMIN(sqrt((q.x-p1.x)*(q.x-p1.x)+(q.y-p1.y)*(q.y-p1.y)),sqrt((q.x-p2.x)*(q.x-p2.x)+(q.y-p2.y)*(q.y-p2.y))); }10.求两直线的交点语法:result=mindistance(Point p1,Point p2,Point q); 参数:p1~直线上不相同的两点p4:*p:通过指针返回结果返回1:两直线相交;2:两直线平行值:注意:源程序:如需要判断两线段交点,检验k和对应k1(注释中)的值是否在0~1之间,用在0~1之间的那个求交点ACM常考算法typedef struct { double x,y; } Point;int linecorss(Point p1,Point p2,Point p3,Point p4,Point *p) {double k; //同一直线if ((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x)==0(p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x)==0) return 2; //平行,不同一直线if ((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)==0) return 0;k=((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y));//k1=((p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)); (*p).x=p1.x+k*(p2.x-p1.x);(*p).y=p1.y+k*(p2.y-p1.y); return 1;//有交点}11.判断一个封闭图形是凹集还是凸集语法:result=convex(Point *p,int n); 参数:*p:封闭曲线顶点数组n:封闭曲线顶点个数返回1:凸集;-1:凹集;0:曲线不符合要求无法计算值:注意:源程序:默认曲线为简单曲线:无交叉、无圈typedef struct { double x,y; } Point;。

16个ACM经典算法介绍

16个ACM经典算法介绍
和 a[q+1:r]进行排序。 ③合并:由于对 a[p:q-1]和 a[q+1:r]的排序是就地进行的,
所以在 a[p:q-1]和 a[q+1:r]都已排好的序后,不需要执行任何计算,a[p:r]就
已排好序。 b. 用函数 maxtap()求出最大差值。 4、源程序: #include<iostream.h> #include<stdio.h> double a[1000000]; template<class Type> void swap(Type &x,Type &y) {
cout<<sn[i]<<'\n'; } 5、算法分析:
函数 count()的复杂度为 O(1),主函数调用 count(),故该
算法的时间复杂度为 O(1)。 实验二 最大间隙问题 1、问题描述:
最大间隙问题:给定 n 个实数 x1 , x2 ,... , xn,求这 n 个 数在实轴上相邻2 个数之间的最大差值。假设对任何实数的 下取整函数耗时 O(1),设计解最大间隙问题的线性时间算法。 对于给定的 n 个实数 x1 , x2 ,... , xn,编程计算它们的 最大间隙。
a. 统计从个位算起前 j 位0~9个数; b. 如果 j+1位为0,去掉第 j+1位补0个数; c. 统计第 j+1位出现1~(r-1)个数; d. 统计第 j+1位出现 r 个数。 4、源程序: #include <iostream.h> int main()
{ long int sn[10]; int i,n,c,k,s,pown; for(i=0;i<10;i++) sn[i]=0;

清华大学ACM集训队培训资料(内部使用)

清华大学ACM集训队培训资料(内部使用)
cout << pounds << " pounds." << endl;
return 0;
}
int stonetolb(int sts)
{
return 14 * sts;
}
下面是运行情况:
Enter the weight in sone:14
14 stone = 196 pounds.
程序通过cin语句给stone提供一个值,然后在main函数中,把这个值传递给stonetolb()函数,这个植被赋给sts之后,stonetolb()用return将14*sts返回给main()。
type functionname (argumentlist)
{
statements
}
注意,定义simon()的代码在main()函数的后面,C++中不允许将函数定义在另一个函数内。每个函数的定义都是独立的,所有的函数的创建都是平等的。
simon()函数的函数头定义如下:
void simon(int n)
清华大学ACM集训队培训资料(内部使用)
一、C++基础
基本知识
所有的C++程序都是有函数组成的,函数又叫做子程序,且每个C++程序必须包含一个main函数,编译器(能够把源代码转换成目标代码的程序)把翻译后的目标代码和一些启动代码组合起来,生成可执行文件,main函数就是可执行文件的入口,所以,每个C++程序有且只有一个main函数。
如果我们修改程序1.1中的main()函数的名称,将其改为Main(),那么,IDE就会给出错误信息,比如“[Linker error] undefined reference to `WinMain@16'”,因为编译器没有找到main函数。

ACM培训资料数据结构和算法

ACM培训资料数据结构和算法

初 始 化 邻 接 矩 阵 arcs, 将 所 有 边 上 的 权 值 置 为 ∞
读 入 边 (v1 ,v2 )和 权 值 w
根 据 顶 点 v 1 ,v 2 查 找 顶 点 向 量 , 确 定 其 存 储 位 置 i,j
令 : G .a rc s [i][j].a d j= w ,若 有 相 关 信 息 , 输 入 弧 的 相 关 信 息 到 In fo ; 令 G .a rc s [j][i].a d j= w
2020/4/9
27
7.3.2 广度优先搜索 BFS
1)基本思想:
– 任选图中一个顶点 v ,访问此顶点,并作访问 标记。
– 从 v 出发,依次访问 v 的各个未曾被访问过的 邻接顶点 w1, w2, …, wt,并作访问标记。
– 然后再顺序访问 w1, w2, …, wt 的所有还未被访 问过的邻接顶点,并作访问标记。
N 已 读 入 arcnum 条 边 了 吗 ? Y
结束
13
7.2.2 邻接表 (Adjacency
1) 存储特点
List)
– 对于图G中的每个顶点vi,把所有邻接于vi的顶点vj链成一 个单链表,这个单链表称为顶点vi的邻接表;
– 将所有点的邻接表表头放到数组中,就构成了图的邻接表
2020/4/9
}Mgragh; /*Maragh是以邻接矩阵存储的图*/
2020/4/9
12
4)图的创建
创建以邻接矩阵存储的无向网
▪ 思路: 输 入 图 中 边 的 数 目 arcnum , 顶 点 数 目 vexnum
2020/4/9
依 次 读 入 vexnum 个 顶 点 信 息 , 存 入 顶 点 向 量

ACM程序设计常用算法与数据结构参考共113页word资料

ACM程序设计常用算法与数据结构参考共113页word资料

ACM程序设计常用算法与数据结构参考Tomsdinary目录前言 (5)排序算法 (7)插入排序 (7)选择排序 (8)冒泡排序 (9)希尔排序 (9)随机化快速排序 (11)归并排序 (13)堆排序 (15)大整数处理 (16)包含头文件 (16)定义 (16)实现 (18)流输出 (18)流输入 (19)赋值 (19)转换函数 (19)规范化符号化 (20)带符号乘法 (20)无符号取模 (20)整数乘法 (21)整数加法 (23)带符号加法 (24)浮点乘法 (25)浮点加法 (26)带符号减法 (27)整数减法 (28)浮点减法 (30)带符号比较 (31)无符号比较 (31)无符号乘方 (32)带符号乘方 (33)使用方法 (33)高级数据结构 (34)普通二叉搜素树 (34)定义 (34)实现 (36)删树 (38)插入元素到树 (38)复制树 (40)求树的高度 (42)求叶子的个数 (43)删除元素 (43)使用方法 (45)基本线段树模式 (45)基本并查集模式 (47)散列实现的一种方式参考 (48)定义与实现 (48)使用方法 (53)堆 (54)包含头文件 (54)定义与实现 (54)使用方法 (56)图相关算法 (56)图的深度优先和广度优先算法举例 (56)无向图最小生成树的Kruskal算法举例 (58)无向图最小生成树的Prim算法举例 (59)有向图的单源最短路径Dijkstra算法举例 (60)有向图的多源最短路径Floyd算法举例 (62)拓扑排序举例 (62)AOE网的算法举例 (64)求图的一个中心算法举例 (67)求图的P个中心算法举例 (69)SPFA算法举例 (71)割顶和块的算法举例 (73)计算几何算法 (75)向量模 (75)向量点积 (75)向量叉积 (75)左右判断 (76)相交判断 (76)正规相交交点 (76)判断多边形凸 (76)任意多变形面积 (77)凸包问题的快包实现举例 (77)STL算法参考 (81)accumulate() (81)adjacent_difference() (81)binary_search() (82)copy() (82)copy_backward() (83)count() (83)count_if() (83)equal() (83)equal_range() (84)fill() (84)fill_n() (84)find() (85)find_if() (85)find_end() (85)find_first_of() (86)for_each() (86)generate() (86)generate_n() (86)includes() (87)inner_product() (87)inplace_merge() (88)iter_swap() (88)lexicographical_compare() (88)lower_bound() (89)max() (89)max_element() (90)min() (90)min_element() (90)merge() (91)mismatch() (91)next_permutation() (91)nnth_element() (92)partial_sort() (92)partial_sort_copy() (93)partial_sum() (93)prev_permutation() (94)random_shuffle() (94)remove() (95)remove_copy() (95)remove_if() (95)remove_copy_if() (95)replace() (96)replace_copy() (96)replace_if() (96)replace_copy_if() (96)reverse_copy() (97)rotate() (97)rotate_copy() (97)search() (98)search_n() (98)set_difference() (98)set_intersection() (99)set_symmetric_difference() (99)set_union() (100)sort() (100)stable_partition() (101)stable_sort() (101)swap() (101)swap_range() (101)transform() (102)unique() (102)unique_copy() (103)upper_bound() (103)make_heap() (104)pop_heap() (104)push_heap() (104)sort_heap() (105)字符串处理 (105)KMP算法举例 (105)C++语言可用头文件 (106)<algorithm> (106)<bitset> (106)<complex> (107)<deque> (107)<exception> (107)<fstream> (107)<functional> (107)<iomanip> (107)<ios> (107)<iosfwd> (107)<iostream> (108)<iso646.h> (108)<istream> (108)<iterator> (108)<limits> (108)<list> (108)<locale> (108)<map> (109)<new> (109)<numeric> (109)<ostream> (109)<queue> (109)<set> (109)<sstream> (109)<stack> (110)<stdexcept> (110)<streambuf> (110)<string> (110)<strstream> (110)<utility> (110)<valarray> (110)<vector> (110)<cassert> (111)<cctype> (111)<cerrno> (111)<cfloat> (111)<ciso646> (111)<climits> (111)<clocale> (111)<cmath> (111)<csetjmp> (111)<csignal> (112)<cstdarg> (112)<cstddef> (112)<cstdio> (112)<cstdlib> (112)<cstring> (112)<ctime> (112)<cwchar> (112)<cwctype> (112)前言如今的程序设计已不再是个人英雄时代了,程序的设计和开发实施需要靠团队成员的积极配合和合作。

ACM常用算法介绍及实用模板

ACM常用算法介绍及实用模板

河南大学ACM常用算法介绍及模板河南大学计算机与信息工程学院1一、数学问题 (7)1. 精度计算——大数阶乘 (7)2.精度计算——乘法(大数乘小数)....................................................... 错误!未定义书签。

3.精度计算——乘法(大数乘大数) (8)4.精度计算——加法 (10)5.精度计算——减法 (11)6.精度计算——除法约分 (13)7.任意进制转换 (19)8.最大公约数、最小公倍数 (21)9.组合序列 (22)10.Ronberg算法计算积分 (25)11.行列式计算 (26)12.求排列组合数 (27)二、计算几何 (27)1.叉乘法求任意多边形面积 (28)2.求三角形面积 (29)3.求多边形重心 (30)4.两矢量间角度 (31)5.两点距离(2D、3D) (32)6.射向法判断点是否在多边形内部 (33)7.判断点是否在线段上 (35)29.判断线段与直线是否相交 (39)10.点到线段最短距离 (40)11.求两直线的交点 (42)12.判断一个封闭图形是凹集还是凸集 (43)13.Graham扫描法寻找凸包 (43)三、数论 (50)1.x的二进制长度 (50)2.返回x的二进制表示中从低到高的第i位 (51)3.模取幂运算(反复平方法求数的幂) (51)4.求解模线性方程 (54)5.求解模线性方程组(中国余数定理) (56)6.筛法素数产生器 (58)7.判断一个数是否素数 (61)8.初等数论里的欧拉公式: (61)9.数的分解 (65)10.关于数的阶乘 (67)11.母函数 (69)四、图论 (78)1. 深度优先搜索 (82)2. 边分类算法 (84)3. 连通性 (85)35. 无向图的割顶和桥 (93)6. 欧拉图 (99)1)消圈法(逐步插入回路法) (100)2)Fleury算法(能不走桥就不走桥): (104)7.最小生成树 (114)1).Prim算法(邻接矩阵,无优化): (114)2).Prim算法(邻接表+Heap优先队列优化): (116)3) Kruskal算法: (124)8.Dijkstra算法求单源最短路径 (128)1).邻接矩阵,无优化 (128)2).邻接链表,用优先队列(STL)优化 (133)9.Bellman-ford算法求单源最短路径 (138)10.Floyd-Warshall算法求每对节点间最短路径 (141)五、最大流 (143)1.最大流算法(Ford-Fulkerson) (143)2.最大二分匹配(最大流算法) (146)3.最大二分匹配(匈牙利算法) (150)4.最佳二分匹配(KM算法) (152)5.最小路径覆盖(最大流算法) (159)6.最小路径覆盖(匈牙利算法) (163)7. 关于匹配 (166)41.快速排序 (167)2.希尔排序 (168)3.选择法排序 (170)4.二分查找 (171)七.数据结构 (173)1. 并查集 (173)2. 串的匹配(KMP算法): (182)3. 字典树(字符串的储存与查找): (185)4. 二叉堆(用二叉堆排序及构建优先队列) (189)5. 二叉查找树(可作为优先队列) (194)6. 红黑树 (200)7. 树状数组 (215)1).一维数组代码(子段和): (216)2).二维数组代码(子阵和): (218)8. 线段树 (221)9. 归并树 (228)10. 后缀数组(Suffix Array) (233)八.博弈问题例题分析 (239)例1.POJ1740 A New Stone Game (240)例2.MIPT100 Nim Game -- who is the winner? (242)例3.POJ1704 Georgia and Bob (243)5例4的另种解法: (246)九.其它算法 (246)1. LCS算法 (249)2. 背包问题 (251)3. 回溯法 (256)4. RMQ问题的ST算法 (259)5. 最近公共祖先(LCA)问题 (263)1).RMQ求法 (264)2).Tarjan的脱机(离线)算法 (264)十.杂谈 (280)1.国际象棋 (280)2.STL常用结构简单用法 (280)3.图的度序列 (286)6一、数学问题1. 精度计算——大数阶乘返回值:阶乘结果的位数注意:本程序直接输出n!的结果,需要返回结果请保留long a[] 需要头文件:cmath源程序:int factorial(int n){long a[10000];int i,j,l,c,m=0,w;a[0]=1;for(i=1;i<=n;i++){c=0;for(j=0;j<=m;j++){a[j]=a[j]*i+c;c=a[j]/10000;a[j]=a[j]%10000;7if(c>0){m++;a[m]=c;}}w=m*4+(int)log10((double)a[m])+1;//阶乘的位数printf("%ld",a[m]);for(i=m-1;i>=0;i--)printf("%4.4ld",a[i]);printf("\n");return w;}2.精度计算——乘法(大数乘大数)#include<iostream>#include<sstream>using namespace std;string muling(string s1,string s2){8for(int n2=s2.length()-1;n2>=0;n2--)if(s2[n2])for(int n1=s1.length()-1,n=n2+s1.length();n1>=0;--n1,--n){int temp=(s1[n1]-'0')*(s2[n2]-'0');cheng[n-1]=char(cheng[n-1]+(cheng[n]+temp-'0')/10);cheng[n]=char((cheng[n]+temp-'0')%10+'0');}int loc=cheng.find_first_not_of('0');if(loc==-1)return"0";return cheng.substr(loc);}int main(){string s1,s2;cin>>s1>>s2;cout<<muling(s1,s2)<<endl;return 0;}9#include<sstream>#include<iostream>using namespace std;string sum(string s1,string s2){if(s1.length()<s2.length()){string temp=s1;s1=s2;s2=temp;}for(int n1=s1.length()-1,n2=s2.length ()-1;n1>=0;n1--,n2--) {s1[n1]=char(s1[n1]+(n2>=0?s2[n2]-'0':0));if(s1[n1]-'0'>=10){s1[n1]=char((s1[n1]-'0')%10+'0');if(n1)s1[n1-1]++; //想想为什么?如果不是十进制呢?elses1='1'+s1;}return s1;}int main(){for(string s1,s2;cin>>s1>>s2;) cout<<sum(s1,s2)<<endl; return 0;}4.精度计算——减法#include<sstream>#include<iostream>using namespace std;bool compare(string s1,string s2) {if(s1.length()<s2.length())return true;if(s1.length()==s2.length()){if(s1[i]<s2[i])return true;}return false;}//========================================== string subing(string s1,string s2){bool sign=0;if(s1==s2)return "0";//所以有0-0结果仍正确!if(compare(s1,s2)){string temp=s1;s1=s2;s2=temp;sign=1;}for(int n1=s1.length()-1,n2=s2.length ()-1;n1>=0;n1--,n2--){s1[n1]=char(s1[n1]-(n2>=0?s2[n2]-'0':0));{s1[n1]+=10;s1[n1-1]--;}}if(sign)return '-'+s1.substr(s1.find_first_not_of('0'));return s1.substr(s1.find_first_not_of('0'));}//==================================================== =======int main(){for(string s1,s2;cin>>s1>>s2;)cout<<subing(s1,s2)<<endl;return 0;}5.精度计算——除法约分#include<iostream>#include<sstream>//================================ typedef struct Data{string s1,s2;}Data;//两正的大数比较大小前者大返回1 相等返回0后者大返回-1 int MoreThan(string s1,string s2){if(s1.length()>s2.length())return 1;if(s1.length()<s2.length())return -1;int i;for(i=0;i<s1.length();i++){if(s1[i] != s2[i]){if(s1[i]>s2[i])return 1;elsereturn -1;}return 0;}//=============大数减法==============string OpsitionSub(string s1,string s2){。

ACM常用算法及练习

ACM常用算法及练习

ACM常用算法及练习第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打出来.1.最短路(Floyd、Dijstra,BellmanFord)2.最小生成树(先写个prim,kruscal要用并查集,不好写)3.大数(高精度)加减乘除4.二分查找. (代码可在五行以内)5.叉乘、判线段相交、然后写个凸包.6.BFS、DFS,同时熟练hash表(要熟,要灵活,代码要简)7.数学上的有:辗转相除(两行内),线段交点、多角形面积公式.8. 调用系统的qsort, 技巧很多,慢慢掌握.9. 任意进制间的转换第二阶段:练习复杂一点,但也较常用的算法。

如:1. 二分图匹配(匈牙利),最小路径覆盖2. 网络流,最小费用流。

3. 线段树.4. 并查集。

5. 熟悉动态规划的各个典型:LCS、最长递增子串、三角剖分、记忆化dp6.博弈类算法。

博弈树,二进制法等。

7.最大团,最大独立集。

8.判断点在多边形内。

9. 差分约束系统.10. 双向广度搜索、A*算法,最小耗散优先.相关的知识图论路径问题0/1边权最短路径BFS非负边权最短路径(Dijkstra)可以用Dijkstra解决问题的特征负边权最短路径Bellman-FordBellman-Ford的Yen-氏优化差分约束系统Floyd广义路径问题传递闭包极小极大距离/ 极大极小距离Euler Path / Tour圈套圈算法混合图的Euler Path / TourHamilton Path / Tour特殊图的Hamilton Path / Tour 构造生成树问题最小生成树第k小生成树最优比率生成树0/1分数规划度限制生成树连通性问题强大的DFS算法无向图连通性割点割边二连通分支有向图连通性强连通分支2-SAT最小点基有向无环图拓扑排序有向无环图与动态规划的关系二分图匹配问题一般图问题与二分图问题的转换思路最大匹配有向图的最小路径覆盖0 / 1矩阵的最小覆盖完备匹配最优匹配稳定婚姻网络流问题网络流模型的简单特征和与线性规划的关系最大流最小割定理最大流问题有上下界的最大流问题循环流最小费用最大流/ 最大费用最大流弦图的性质和判定组合数学解决组合数学问题时常用的思想逼近递推/ 动态规划概率问题Polya定理计算几何/ 解析几何计算几何的核心:叉积/ 面积解析几何的主力:复数基本形点直线,线段多边形凸多边形/ 凸包凸包算法的引进,卷包裹法Graham扫描法水平序的引进,共线凸包的补丁完美凸包算法相关判定两直线相交两线段相交点在任意多边形内的判定点在凸多边形内的判定经典问题最小外接圆近似O(n)的最小外接圆算法点集直径旋转卡壳,对踵点多边形的三角剖分数学/ 数论最大公约数Euclid算法扩展的Euclid算法同余方程/ 二元一次不定方程同余方程组线性方程组高斯消元法解mod 2域上的线性方程组整系数方程组的精确解法矩阵行列式的计算利用矩阵乘法快速计算递推关系分数分数树连分数逼近数论计算求N的约数个数求phi(N)求约数和快速数论变换……素数问题概率判素算法概率因子分解数据结构组织结构二叉堆左偏树二项树胜者树跳跃表样式图标斜堆reap统计结构树状数组虚二叉树线段树矩形面积并圆形面积并关系结构Hash表并查集路径压缩思想的应用STL中的数据结构vectordequeset / map动态规划/ 记忆化搜索动态规划和记忆化搜索在思考方式上的区别最长子序列系列问题最长不下降子序列最长公共子序列最长公共不下降子序列一类NP问题的动态规划解法树型动态规划背包问题动态规划的优化四边形不等式函数的凸凹性状态设计规划方向线性规划常用思想二分最小表示法串KMP Trie结构后缀树/后缀数组LCA/RMQ有限状态自动机理论排序选择/冒泡快速排序堆排序归并排序基数排序拓扑排序排序网络中级:一.基本算法:(1)C++的标准模版库的应用. (poj3096,poj3007)(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)二.图算法:(1)差分约束系统的建立和求解. (poj1201,poj2983)(2)最小费用最大流(poj2516,poj2516,poj2195)(3)双连通分量(poj2942)(4)强连通分支及其缩点.(poj2186)(5)图的割边和割点(poj3352)(6)最小割模型、网络流规约(poj3308, )三.数据结构.(1)线段树. (poj2528,poj2828,poj2777,poj2886,poj2750)(2)静态二叉检索树. (poj2482,poj2352)(3)树状树组(poj1195,poj3321)(4)RMQ. (poj3264,poj3368)(5)并查集的高级应用. (poj1703,2492)(6)KMP算法. (poj1961,poj2406)四.搜索(1)最优化剪枝和可行性剪枝(2)搜索的技巧和优化(poj3411,poj1724)(3)记忆化搜索(poj3373,poj1691)五.动态规划(1)较为复杂的动态规划(如动态规划解特别的施行商问题等)(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)(2)记录状态的动态规划. (POJ3254,poj2411,poj1185)(3)树型动态规划(poj2057,poj1947,poj2486,poj3140)六.数学(1)组合数学:1.容斥原理.2.抽屉原理.3.置换群与Polya定理(poj1286,poj2409,poj3270,poj1026).4.递推关系和母函数.(2)数学.1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)2.概率问题. (poj3071,poj3440)3.GCD、扩展的欧几里德(中国剩余定理) (poj3101)(3)计算方法.1.0/1分数规划. (poj2976)2.三分法求解单峰(单谷)的极值.3.矩阵法(poj3150,poj3422,poj3070)4.迭代逼近(poj3301)(4)随机化算法(poj3318,poj2454)(5)杂题.(poj1870,poj3296,poj3286,poj1095)七.计算几何学.(1)坐标离散化.(2)扫描线算法(例如求矩形的面积和周长并,常和线段树或堆一起使用).(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)(3)多边形的内核(半平面交)(poj3130,poj3335)(4)几何工具的综合应用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)高级:一.基本算法要求:(1)代码快速写成,精简但不失风格(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)(2)保证正确性和高效性. poj3434二.图算法:(1)度限制最小生成树和第K最短路. (poj1639)(2)最短路,最小生成树,二分图,最大流问题的相关理论(主要是模型建立和求解)(poj3155,poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446(3)最优比率生成树. (poj2728)(4)最小树形图(poj3164)(5)次小生成树.(6)无向图、有向图的最小环三.数据结构.(1)trie图的建立和应用. (poj2778)(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和在线算法(RMQ+dfs)).(poj1330)(3)双端队列和它的应用(维护一个单调的队列,常常在动态规划中起到优化状态转移的目的). (poj2823)(4)左偏树(可合并堆).(5)后缀树(非常有用的数据结构,也是赛区考题的热点).(poj3415,poj3294)四.搜索(1)较麻烦的搜索题目训练(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)(2)广搜的状态优化:利用M进制数存储状态、转化为串用hash表判重、按位压缩存储状态、双向广搜、A*算法.(poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)(3)深搜的优化:尽量用位运算、一定要加剪枝、函数参数尽可能少、层数不易过大、可以考虑双向搜索或者是轮换搜索、IDA*算法.(poj3131,poj2870,poj2286)五.动态规划(1)需要用数据结构优化的动态规划.(poj2754,poj3378,poj3017)(2)四边形不等式理论.(3)较难的状态DP(poj3133)六.数学(1)组合数学.1.MoBius反演(poj2888,poj2154)2.偏序关系理论.(2)博奕论.1.极大极小过程(poj3317,poj1085)2.Nim问题.七.计算几何学.(1)半平面求交(poj3384,poj2540)(2)可视图的建立(poj2966)(3)点集最小圆覆盖.(4)对踵点(poj2079)八.综合题.(poj3109,poj1478,poj1462,poj2729,poj2048,poj3336,poj3315,poj2148,poj1263 )初期:一.基本算法:(1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586)(3)递归和分治法. (4)递推.(5)构造法.(poj3295) (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法:(1)图的深度优先遍历和广度优先遍历.(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)(3)最小生成树算法(prim,kruskal)(poj1789,poj2485,poj1258,poj3026)(4)拓扑排序(poj1094)(5)二分图的最大匹配(匈牙利算法) (poj3041,poj3020)(6)最大流的增广路算法(KM算法). (poj1459,poj3436)三.数据结构.(1)串(poj1035,poj3080,poj1936)(2)排序(快排、归并排(与逆序数有关)、堆排) (poj2388,poj2299)(3)简单并查集的应用.(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)(5)哈夫曼树(poj3253)(6)堆(7)trie树(静态建树、动态建树) (poj2513)四.简单搜索(1)深度优先搜索(poj2488,poj3083,poj3009,poj1321,poj2251)(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)五.动态规划(1)背包问题. (poj1837,poj1276)(2)型如下表的简单DP(可参考lrj的书page149):1.E[j]=opt (poj3267,poj1836,poj1260,poj2533)2.E[i,j]=opt (最长公共子序列)(poj3176,poj1080,poj1159)3.C[i,j]=w[i,j]+opt.(最优二分检索树问题)六.数学(1)组合数学:1.加法原理和乘法原理.2.排列组合.3.递推关系.(POJ3252,poj1850,poj1019,poj1942)(2)数论.1.素数与整除问题2.进制位.3.同余模运算.(poj2635, poj3292,poj1845,poj2115)(3)计算方法.1.二分法求解单调函数相关知识.(poj3273,poj3258,poj1905,poj3122)七.计算几何学.(1)几何公式.(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等).(poj2031,poj1039)(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)(poj1408,poj1584)(4)凸包. (poj2187,poj1113)2|评论(1)。

ACM常用经典算法

ACM常用经典算法

ACM常⽤经典算法时间复杂度(渐近时间复杂度的严格定义,NP问题,时间复杂度的分析⽅法,主定理)排序算法(平⽅排序算法的应⽤,Shell排序,快速排序,归并排序,时间复杂度下界,三种线性时间排序,外部排序)数论(整除,集合论,关系,素数,进位制,辗转相除,扩展的辗转相除,同余运算,解线性同余⽅程,中国剩余定理)指针(链表,搜索判重,邻接表,开散列,⼆叉树的表⽰,多叉树的表⽰)按位运算(and,or,xor,shl,shr,⼀些应⽤)图论(图论模型的建⽴,平⾯图,欧拉公式与五⾊定理,求强连通分量,求割点和桥,欧拉回路,AOV问题,AOE问题,最⼩⽣成树的三种算法,最短路的三种算法,标号法,差分约束系统,验证⼆分图,Konig定理,匈⽛利算法,KM算法,稳定婚姻系统,最⼤流算法,最⼩割最⼤流定理,最⼩费⽤最⼤流算法)计算⼏何(平⾯解⼏及其应⽤,向量,点积及其应⽤,叉积及其应⽤,半平⾯相交,求点集的凸包,最近点对问题,凸多边形的交,离散化与扫描)数据结构(⼴度优先搜索,验证括号匹配,表达式计算,递归的编译,Hash表,分段Hash,并查集,Tarjan算法,⼆叉堆,左偏树,⼆斜堆,⼆项堆,⼆叉查找树,红⿊树,AVL平衡树,Treap,Splay,静态⼆叉查找树,2-d树,线段树,⼆维线段树,矩形树,Trie树,块状链表)组合数学(排列与组合,鸽笼原理,容斥原理,递推,Fibonacci数列,Catalan数列,Stirling数,差分序列,⽣成函数,置换,Polya原理)概率论(简单概率,条件概率,Bayes定理,期望值)矩阵(矩阵的概念和运算,⼆分求解线性递推⽅程,多⽶诺⾻牌棋盘覆盖⽅案数,⾼斯消元)字符串处理(KMP,后缀树,有限状态⾃动机,Huffman编码,简单密码学)动态规划(单调队列,凸完全单调性,树型动规,多叉转⼆叉,状态压缩类动规,四边形不等式)博奕论(Nim取⼦游戏,博弈树,Shannon开关游戏)搜索(A*,ID,IDA*,随机调整,遗传算法)微积分初步(极限思想,导数,积分,定积分,⽴体解析⼏何)。

ACM常见算法

ACM常见算法

ACM常见算法ACM算法⼀、数论算法 1.求两数的最⼤公约数 2.求两数的最⼩公倍数 3.素数的求法 A.⼩范围内判断⼀个数是否为质数: B.判断longint范围内的数是否为素数(包含求50000以内的素数表):⼆、图论算法1.最⼩⽣成树A.Prim算法:B.Kruskal算法:(贪⼼) 按权值递增顺序删去图中的边,若不形成回路则将此边加⼊最⼩⽣成树。

2.最短路径 A.标号法求解单源点最短路径: B.Floyed算法求解所有顶点对之间的最短路径: C. Dijkstra 算法:3.计算图的传递闭包4.⽆向图的连通分量 A.深度优先 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], 若边I由<j,k>表⽰,则Ee[I] = Ve[j]; d. 边活动最晚开始时间 El[I], 若边I由<j,k>表⽰,则El[I] = 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回路定义:经过图的每个顶点仅⼀次的回路。

免费-ACM常用算法计算几何——吴翼-64页文档资料

免费-ACM常用算法计算几何——吴翼-64页文档资料
在边界上情况的特殊判断
◦ 一个避免精度问题的加速方法
Authored by Will, IIIS, THU 2020/1/21
8
预备知识:距离与交点的计算
点的距离计算
◦ 线段,直线 ◦ 圆,多边形
线段相关
◦ 线段距离? ◦ 线段的交点?
圆相关
◦ 直线与圆的距离与交点 ◦ 点与圆的切点 ◦ 两圆的公切点
计算方法
◦ 类似Monotone Chain O(NlogN)
更一般的性质与问题
◦ 简单正交多边形的正交凸包 ◦ 口袋的面积 ◦ 最小的周长
Authored by Will, IIIS, THU 2020/1/21
16
凸包上的序——凸性
凸包的定向 直线与凸包 矩形覆盖问题 点与凸包 凸包与凸包 凸包上的动态计算问题 凸包的划分问题
◦ 线段的相交测试 ◦ 面积的计算
右手方向与左手方向
Authored by Will, IIIS, THU 2020/1/21
7
预备知识:另一个例子
判断点在多边形内部
◦ 凸多边形 ◦ 简单多边形
射线法——效率高!
◦ 共线的处理?
随机斜率 纵切变换
转角法——优美!
◦ 精度问题?
浅谈一些几何问题
清华大学 交叉信息院 吴翼 Will
Authored by Will, IIIS, THU 2020/1/21
1
前言:计算几何与计算机科学
机械自动控制 地理信息贪测 计算机辅助设计 模式识别
◦ 人脸识别 ◦ 相关图像处理
游戏领域
◦ 碰撞检测 ◦ 光线追踪 ◦ 三维场景渲染

ACM超级经典算法大集合

ACM超级经典算法大集合

因式分解 完美数阿姆斯壮数 最大访客数中序式转后序式(前序式) hit maiiiO ( hit n;printf (”请输入盘数:”); scanf (”%d”, &n); hanoi(n, a, B,。

); return 0;超级经典算法大集合: 老掉牙 河内塔 费式数列 巴斯卡三角形 三色棋老鼠走迷官(一) 老鼠走迷官(二) 骑士走棋盘 八个皇后 八枚银币 生命游戏 字串核对 双色、三色河内塔 背包问题(Knapsack Problem )数、运算 蒙地卡罗法求PI Eratosthenes 筛选求质数 超长整数运算(大数运算) 长PI最大公因数、最小公倍数、 后序式的运算 关于赌博 洗扑克牌(乱数排列) Craps 赌博游戏 约瑟夫问题(Josephus集合问题 排列组合格雷码(Gray Code ) 产生可能的集合m 元素集合的n 个元素子集 数字拆解 排序得分排行选择、插入、气泡排序 SheU 排序法-改良的插入 排序Shakei-排序法-改良的气 泡排序Heap 排序法-改良的选择 排序 快速排序法(一) 快速排序法(二) 快速排序法(三) 合并排序法 基数排序法 捜寻循序搜寻法(使用卫兵) 二分捜寻法(捜寻原则的 代表) 插补捜寻法 费氏捜寻法 矩阵稀疏矩阵多维矩阵转一维矩阵上三角、下三角、对称矩 阵 奇数魔方阵 4N 魔方阵2(2N+1)魔方阵1.河内之塔说明河内之塔(Towers of Hanoi )是法国人M.Claiis (Lucas )于1883年从泰国带至法国的,河内为越 战时北越的首都,即现在的胡志明市;1883年法国数学家Edouard Lucas 曾提及这个故事,据 说创世纪时Benares 有一座波罗教塔,是由三支钻石棒(Pag )所支撑,开始时神在第一根棒上 放置64个由上至下依由小至大排列的金盘(Disc ),并命令僧侣将所有的金盘从第一根石棒移 至第三根石棒,且搬运过程中遵守大盘子在小盘子之下的原则,若每日仅搬一个盘子,则当盘 子全数搬运完毕之时,此塔将毁损,而也就是世界末日来临之时。

16个ACM经典算法介绍

16个ACM经典算法介绍

16个ACM经典算法介绍一、排序算法:1.冒泡排序:基于比较的排序算法,通过不断交换相邻元素将最大元素逐渐向后移动。

2.插入排序:基于比较的排序算法,通过将元素逐个插入到已排好序的部分中,最终得到完全有序的序列。

3.归并排序:基于分治的排序算法,将待排序序列划分为一系列子序列,然后将子序列进行合并,最终得到完全有序的序列。

4.快速排序:基于分治的排序算法,通过选择一个基准元素将序列划分为两部分,然后递归地对两部分进行排序。

5.堆排序:基于堆的排序算法,通过构建最大堆或最小堆来实现排序。

二、查找算法:6.二分查找:基于有序序列的查找算法,通过将待查找值与序列中间元素进行比较,逐渐缩小查找范围。

7.哈希表:基于哈希函数的查找算法,通过将键值对存储在哈希表中,实现高效的查找。

三、图算法:8.深度优先(DFS):基于栈的算法,通过递归地访问顶点的邻接顶点,实现图的遍历。

9.广度优先(BFS):基于队列的算法,通过访问顶点的邻接顶点,实现图的遍历。

10. 最小生成树算法:用来求解无向图的最小生成树,常用的有Prim算法和Kruskal算法。

11. 最短路径算法:用来求解有向图或带权重的无向图的最短路径,常用的有Dijkstra算法和Floyd-Warshall算法。

四、动态规划算法:12.最长上升子序列(LIS):用来求解一个序列中最长严格递增子序列的长度。

13.背包问题:用来求解在给定容量下,能够装入尽量多的物品的问题。

五、字符串算法:14.KMP算法:用来在一个文本串S中查找一个模式串P的出现位置的算法,通过预处理模式串,利用已经匹配过的子串,跳过一定长度进行下一轮匹配。

15. Boyer-Moore算法:用来在一个文本串S中查找一个模式串P的出现位置的算法,通过从模式串末尾开始匹配,利用好后缀和坏字符规则,跳过一定长度进行下一轮匹配。

16.字符串匹配算法:用来在一个文本串S中查找多个模式串的出现位置的算法,常用的有AC自动机和后缀树。

ACM知识点分类

ACM知识点分类

ACM知识点分类第一类:基础算法(1)基本算法:枚举、贪婪、递归、分治、递归、构造、模拟(2)动态规划:背包问题,树形dp,状态压缩dp,单调性优化,插头dp(3)搜索:dfs,bfs,记忆化搜索,优化与剪枝,双广,a*,ida*,跳舞链第二类:数据结构(1)简单数据结构:链表,栈和队列,串,树和二叉树,图,排序与检索(2)树结构:段树、树数组、字典树、扩展树、左倾树、动态树、lca和rmq、分区树,sbt(3)字符串:KMP、AC自动机、后缀数组、最小表示(4)其他:联合查询集、哈希表、块链表、双向链表第三类:图论(1)最短路径:Dijkstra、Bellman Ford(SPFA优化)、Floyd、heap+Dijkstra、差分约束、k-th短路(2)生成树:prim,Kruskal,度约束最小生成树,最优比率生成树,次小生成树,最小树图,生成树的计数,树的划分,树的枚举(3)匹配问题:二部图的最大匹配(匈牙利算法)、km、2-Sat、同构(4)网络流:最大流、最小代价、最大流、最小割模型、网络流协议(5)其他:拓扑排序,双连通分量,强连通分支及其缩点,图的割边与割点,无向图、有有向图的极小环,欧拉路,哈密顿路,平面图,分层图思想,二部图第四类:数学(1)数论:素数和除法问题,进位系统,同余模算法,整数分解,GCD,扩展欧几里德,求解模线性方程,中国余数定理,元素的幂,rsa公钥加密(2)组合数学:加法和乘法原理,排列和组合原理,递归关系和生成函数,包含排除原理,抽屉原理,置换群与polya定理,mobius反演,偏序关系理论(3)计算方法:二分法求解单调函数的相关知识,二分法求解单峰(单谷)极值,矩阵法,迭代法代逼近,高斯消元法,随机化算法,0/1分数规划(4)高精度问题扩展:倒数、幂、平方、对数、对分快速法、反指数函数、三角函数,数值计算的优化(5)其他:博弈论、线性规划、整数规划、概率问题、多项式和快速傅立叶、数学思想和方法方法的综合运用(构造,猜想,归纳法,反证法)第五类:计算几何(1)(2)(3)(4)(5)(6)(7)判断线段相交,判断直线相交,判断点是否在多边形中,计算凸多边形的面积和重心,求外切圆和内切圆,求凸壳,最近点对问题,最远点对问题,点集或图形集合的最小覆盖圆,点集或图形集合的最小覆盖矩形,矩形的交与并(扫描法),三角剖分,费马点计算,皮克定理,常用几何公式。

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ACM小组内部预定函数数学问题:1.精度计算——大数阶乘2.精度计算——乘法(大数乘小数)3.精度计算——乘法(大数乘大数)4.精度计算——加法5.精度计算——减法6.任意进制转换7.最大公约数、最小公倍数8.组合序列9.快速傅立叶变换(FFT)10.Ronberg算法计算积分11.行列式计算12.求排列组合数字符串处理:1.字符串替换2.字符串查找3.字符串截取计算几何:1.叉乘法求任意多边形面积2.求三角形面积3.两矢量间角度4.两点距离(2D、3D)5.射向法判断点是否在多边形内部6.判断点是否在线段上7.判断两线段是否相交8.判断线段与直线是否相交9.点到线段最短距离10.求两直线的交点11.判断一个封闭图形是凹集还是凸集12.Graham扫描法寻找凸包数论:1.x的二进制长度2.返回x的二进制表示中从低到高的第i位3.模取幂运算4.求解模线性方程5.求解模线性方程组(中国余数定理)6.筛法素数产生器7.判断一个数是否素数图论:1.Prim算法求最小生成树2.Dijkstra算法求单源最短路径3.Bellman-ford算法求单源最短路径4.Floyd算法求每对节点间最短路径排序/查找:1.快速排序2.希尔排序3.选择法排序4.二分查找数据结构:1.顺序队列2.顺序栈3.链表4.链栈5.二叉树一、数学问题1.精度计算——大数阶乘语法:int result=factorial(int n);参数:n: n 的阶乘返回值:阶乘结果的位数注意:本程序直接输出n!的结果,需要返回结果请保留long a[]需要 math.h源程序:int factorial(int n){long a[10000];int i,j,l,c,m=0,w;a[0]=1;for(i=1;i<=n;i++){c=0;for(j=0;j<=m;j++){a[j]=a[j]*i+c;c=a[j]/10000;a[j]=a[j]%10000;}if(c>0) {m++;a[m]=c;}}w=m*4+log10(a[m])+1;printf("\n%ld",a[m]);for(i=m-1;i>=0;i--) printf("%4.4ld",a[i]);return w;}2.精度计算——乘法(大数乘小数)语法:mult(char c[],char t[],int m);参数:c[]:被乘数,用字符串表示,位数不限t[]:结果,用字符串表示m:乘数,限定10以内返回值: null注意:需要 string.h源程序:void mult(char c[],char t[],int m){int i,l,k,flag,add=0;char s[100];l=strlen(c);for (i=0;i<l;i++)s[l-i-1]=c[i]-'0';for (i=0;i<l;i++){k=s[i]*m+add;if (k>=10) {s[i]=k%10;add=k/10;flag=1;} else {s[i]=k;flag=0;add=0;}}if (flag) {l=i+1;s[i]=add;} else l=i;for (i=0;i<l;i++)t[l-1-i]=s[i]+'0';t[l]='\0';}3.精度计算——乘法(大数乘大数)语法:mult(char a[],char b[],char s[]);参数:a[]:被乘数,用字符串表示,位数不限b[]:乘数,用字符串表示,位数不限t[]:结果,用字符串表示返回值: null注意:空间复杂度为 o(n^2)需要 string.h源程序:void mult(char a[],char b[],char s[]){int i,j,k=0,alen,blen,sum=0,res[65][65]={0},flag=0;char result[65];alen=strlen(a);blen=strlen(b);for (i=0;i<alen;i++)for (j=0;j<blen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0');for (i=alen-1;i>=0;i--){for (j=blen-1;j>=0;j--)sum=sum+res[i+blen-j-1][j];result[k]=sum%10;k=k+1;sum=sum/10;}for (i=blen-2;i>=0;i--){for (j=0;j<=i;j++) sum=sum+res[i-j][j];result[k]=sum%10;k=k+1;sum=sum/10;}if (sum!=0) {result[k]=sum;k=k+1;}for (i=0;i<k;i++) result[i]+='0';for (i=k-1;i>=0;i--) s[i]=result[k-1-i];s[k]='\0';while(1){if (strlen(s)!=strlen(a)&&s[0]=='0')strcpy(s,s+1);elsebreak;}4.精度计算——加法语法:add(char a[],char b[],char s[]);参数:a[]:被乘数,用字符串表示,位数不限b[]:乘数,用字符串表示,位数不限t[]:结果,用字符串表示返回值: null注意:空间复杂度为 o(n^2)需要 string.h源程序:void add(char a[],char b[],char back[]){int i,j,k,up,x,y,z,l;char *c;if (strlen(a)>strlen(b)) l=strlen(a)+2; elsel=strlen(b)+2;c=(char *) malloc(l*sizeof(char));i=strlen(a)-1;j=strlen(b)-1;k=0;up=0;while(i>=0||j>=0){if(i<0) x='0'; else x=a[i];if(j<0) y='0'; else y=b[j];z=x-'0'+y-'0';if(up) z+=1;if(z>9) {up=1;z%=10;} else up=0;c[k++]=z+'0';i--;j--;}if(up) c[k++]='1';i=0;c[k]='\0';for(k-=1;k>=0;k--)back[i++]=c[k];back[i]='\0';5.精度计算——减法语法:sub(char s1[],char s2[],char t[]);参数:s1[]:被减数,用字符串表示,位数不限s2[]:减数,用字符串表示,位数不限t[]:结果,用字符串表示返回值: null注意:默认s1>=s2,程序未处理负数情况需要 string.h源程序:void sub(char s1[],char s2[],char t[]){int i,l2,l1,k;l2=strlen(s2);l1=strlen(s1);t[l1]='\0';l1--;for (i=l2-1;i>=0;i--,l1--){if (s1[l1]-s2[i]>=0)t[l1]=s1[l1]-s2[i]+'0';else{t[l1]=10+s1[l1]-s2[i]+'0';s1[l1-1]=s1[l1-1]-1;}}k=l1;while(s1[k]<0) {s1[k]+=10;s1[k-1]-=1;k--;}while(l1>=0) {t[l1]=s1[l1];l1--;}loop:if (t[0]=='0'){l1=strlen(s1);for (i=0;i<l1-1;i++) t[i]=t[i+1];t[l1-1]='\0';goto loop;}if (strlen(t)==0) {t[0]='0';t[1]='\0';}}6.任意进制转换语法:conversion(char s1[],char s2[],long d1,long d2);参数:s[]:原进制数字,用字符串表示s2[]:转换结果,用字符串表示d1:原进制数d2:需要转换到的进制数返回值: null注意:高于9的位数用大写'A'~'Z'表示,2~16位进制通过验证源程序:void conversion(char s[],char s2[],long d1,long d2){long i,j,t,num;char c;num=0;for (i=0;s[i]!='\0';i++){if (s[i]<='9'&&s[i]>='0') t=s[i]-'0'; elset=s[i]-'A'+10;num=num*d1+t;}i=0;while(1){t=num%d2;if (t<=9) s2[i]=t+'0'; else s2[i]=t+'A'-10;num/=d2;if (num==0) break;i++;}for (j=0;j<i/2;j++){c=s2[j];s2[j]=s[i-j];s2[i-j]=c;}s2[i+1]='\0';}7.最大公约数、最小公倍数语法:resulet=hcf(int a,int b)、result=lcd(int a,int b)参数:a:int a,求最大公约数或最小公倍数b:int b,求最大公约数或最小公倍数返回值:返回最大公约数(hcf)或最小公倍数(lcd)注意:lcd 需要连同 hcf 使用源程序:int hcf(int a,int b){int r=0;while(b!=0){r=a%b;a=b;b=r;}return(a);}lcd(int u,int v,int h){return(u*v/h);}8.组合序列语法:m_of_n(int m, int n1, int m1, int* a, int head)参数:m:组合数C的上参数n1:组合数C的下参数m1:组合数C的上参数,递归之用*a: 1~n的整数序列数组head:头指针返回值: null注意:*a需要自行产生初始调用时,m=m1、head=0调用例子:求C(m,n)序列:m_of_n(m,n,m,a,0);源程序:void m_of_n(int m, int n1, int m1, int* a, int head){int i,t;if(m1<0 || m1>n1) return;if(m1==n1){for(i=0;i<m;i++) cout<<a[i]<<' '; // 输出序列cout<<'\n';return;}m_of_n(m,n1-1,m1,a,head); // 递归调用t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;m_of_n(m,n1-1,m1-1,a,head+1); // 再次递归调用t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;}9.快速傅立叶变换(FFT)语法:kkfft(double pr[],double pi[],int n,int k,double fr[],double fi[],int l,int il);参数:pr[n]:输入的实部pi[n]:数入的虚部n,k:满足n=2^kfr[n]:输出的实部fi[n]:输出的虚部l:逻辑开关,0 FFT,1 ifFTil:逻辑开关,0 输出按实部/虚部;1 输出按模/幅角返回值: null注意:需要 math.h源程序:void kkfft(pr,pi,n,k,fr,fi,l,il)int n,k,l,il;double pr[],pi[],fr[],fi[];{int it,m,is,i,j,nv,l0;double p,q,s,vr,vi,poddr,poddi;for (it=0; it<=n-1; it++){m=it; is=0;for (i=0; i<=k-1; i++){j=m/2; is=2*is+(m-2*j); m=j;}fr[it]=pr[is]; fi[it]=pi[is];}pr[0]=1.0; pi[0]=0.0;p=6.283185306/(1.0*n);pr[1]=cos(p); pi[1]=-sin(p);if (l!=0) pi[1]=-pi[1];for (i=2; i<=n-1; i++){p=pr[i-1]*pr[1];q=pi[i-1]*pi[1];s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);pr[i]=p-q; pi[i]=s-p-q;}for (it=0; it<=n-2; it=it+2){vr=fr[it]; vi=fi[it];fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1];}m=n/2; nv=2;for (l0=k-2; l0>=0; l0--){m=m/2; nv=2*nv;for (it=0; it<=(m-1)*nv; it=it+nv)for (j=0; j<=(nv/2)-1; j++){p=pr[m*j]*fr[it+j+nv/2];q=pi[m*j]*fi[it+j+nv/2];s=pr[m*j]+pi[m*j];s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);poddr=p-q; poddi=s-p-q;fr[it+j+nv/2]=fr[it+j]-poddr;fi[it+j+nv/2]=fi[it+j]-poddi;fr[it+j]=fr[it+j]+poddr;fi[it+j]=fi[it+j]+poddi;}}if (l!=0)for (i=0; i<=n-1; i++){fr[i]=fr[i]/(1.0*n);fi[i]=fi[i]/(1.0*n);}if (il!=0)for (i=0; i<=n-1; i++){pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);if (fabs(fr[i])<0.000001*fabs(fi[i])){if ((fi[i]*fr[i])>0) pi[i]=90.0;else pi[i]=-90.0;}elsepi[i]=atan(fi[i]/fr[i])*360.0/6.283185306;}return;}10.Ronberg算法计算积分语法:result=integral(double a,double b);参数:a:积分上限b:积分下限function积分函数f:返回值: f在(a,b)之间的积分值注意:function f(x)需要自行修改,程序中用的是sina(x)/x需要 math.h默认精度要求是1e-5源程序:double f(double x){return sin(x)/x; //在这里插入被积函数}double integral(double a,double b) {double h=b-a;double t1=(1+f(b))*h/2.0;int k=1;double r1,r2,s1,s2,c1,c2,t2; loop:double s=0.0;double x=a+h/2.0;while(x<b){s+=f(x);x+=h;}t2=(t1+h*s)/2.0;s2=t2+(t2-t1)/3.0;if(k==1){k++;h/=2.0;t1=t2;s1=s2;goto loop;}c2=s2+(s2-s1)/15.0;if(k==2){c1=c2;k++;h/=2.0;t1=t2;s1=s2;goto loop;}r2=c2+(c2-c1)/63.0;if(k==3){r1=r2; c1=c2;k++;h/=2.0;t1=t2;s1=s2;goto loop;}while(fabs(1-r1/r2)>1e-5){r1=r2;c1=c2;k++;h/=2.0;t1=t2;s1=s2;goto loop;}return r2;}11.行列式计算语法:result=js(int s[][],int n)参数:s[][]:行列式存储数组n:行列式维数,递归用返回值:行列式值注意:函数中常数N为行列式维度,需自行定义源程序:int js(s,n)int s[][N],n;{int z,j,k,r,total=0;int b[N][N];/*b[N][N]用于存放,在矩阵s[N][N]中元素s[0]的余子式*/if(n>2){for(z=0;z<n;z++){for(j=0;j<n-1;j++)for(k=0;k<n-1;k++)if(k>=z)b[j][k]=s[j+1][k+1]; else b[j][k]=s[j+1][k];if(z%2==0) r=s[0][z]*js(b,n-1); /*递归调用*/else r=(-1)*s[0][z]*js(b,n-1);total=total+r;}}else if(n==2)total=s[0][0]*s[1][1]-s[0][1]*s[1][0];return total;}12.求排列组合数语法:result=P(long n,long m); / result=long C(long n,long m);参数:m:排列组合的上系数n:排列组合的下系数返回值:排列组合数注意:符合数学规则:m<=n源程序:long P(long n,long m){long p=1;while(m!=0){p*=n;n--;m--;}return p;}long C(long n,long m){long i,c=1;i=m;while(i!=0){c*=n;n--;i--;}while(m!=0){c/=m;m--;}return c;}二、字符串处理1.字符串替换语法:replace(char str[],char key[],char swap[]);参数:str[]:在此源字符串进行替换操作key[]:被替换的字符串,不能为空串swap[]:替换的字符串,可以为空串,为空串表示在源字符中删除key[]返回值: null注意:默认str[]长度小于1000,如否,重新设定设定tmp大小需要 string.h源程序:void replace(char str[],char key[],char swap[]){int l1,l2,l3,i,j,flag;char tmp[1000];l1=strlen(str);l2=strlen(key);l3=strlen(swap);for (i=0;i<=l1-l2;i++){flag=1;for (j=0;j<l2;j++)if (str[i+j]!=key[j]) {flag=0;break;}if (flag){strcpy(tmp,str);strcpy(&tmp[i],swap);strcpy(&tmp[i+l3],&str[i+l2]);strcpy(str,tmp);i+=l3-1;l1=strlen(str);}}}2.字符串查找语法:result=strfind(char str[],char key[]);参数:str[]:在此源字符串进行查找操作key[]:被查找的字符串,不能为空串返回值:如果查找成功,返回key在str中第一次出现的位置,否则返回-1注意:需要 string.h源程序:int strfind(char str[],char key[]){int l1,l2,i,j,flag;l1=strlen(str);l2=strlen(key);for (i=0;i<=l1-l2;i++){flag=1;for (j=0;j<l2;j++)if (str[i+j]!=key[j]) {flag=0;break;}if (flag) return i;}return -1;}3.字符串截取语法:mid(char str[],int start,int len,char strback[])参数:str[]:操作的目标字符串start:从第start个字符串开始,截取长度为len的字符len:从第start个字符串开始,截取长度为len的字符strback[]:截取的到的字符返回值: 0:超出字符串长度,截取失败;1:截取成功注意:需要 string.h源程序:int mid(char str[],int start,int len,char strback[]){int l,i,k=0;l=strlen(str);if (start+len>l) return 0;for (i=start;i<start+len;i++)strback[k++]=str[i];strback[k]='\0';return 1;}三、计算几何1.叉乘法求任意多边形面积语法:result=polygonarea(Point *polygon,int N);参数:*polygon:多变形顶点数组N:多边形顶点数目返回值:多边形面积注意:支持任意多边形,凹、凸皆可多边形顶点输入时按顺时针顺序排列源程序:typedef struct {double x,y;} Point;double polygonarea(Point *polygon,int N){int i,j;double area = 0;for (i=0;i<N;i++) {j = (i + 1) % N;area += polygon[i].x * polygon[j].y;area -= polygon[i].y * polygon[j].x;}area /= 2;return(area < 0 ? -area : area);}2.求三角形面积语法:result=area3(float x1,float y1,float x2,float y2,float x3,float y3);参数:x1~3:三角形3个顶点x坐标y1~3:三角形3个顶点y坐标返回值:三角形面积注意:需要 math.h源程序:float area3(float x1,float y1,float x2,float y2,float x3,float y3){float a,b,c,p,s;a=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));b=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));c=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));p=(a+b+c)/2;s=sqrt(p*(p-a)*(p-b)*(p-c));return s;}3.两矢量间角度语法:result=angle(double x1, double y1, double x2, double y2);参数:x/y1~2:两矢量的坐标返回值:两的角度矢量注意:返回角度为弧度制,并且以逆时针方向为正方向需要 math.h源程序:#define PI 3.1415926double angle(double x1, double y1, double x2, double y2){double dtheta,theta1,theta2;theta1 = atan2(y1,x1);theta2 = atan2(y2,x2);dtheta = theta2 - theta1;while (dtheta > PI)dtheta -= PI*2;while (dtheta < -PI)dtheta += PI*2;return(dtheta);}4.两点距离(2D、3D)语法:result=distance_2d(float x1,float x2,float y1,float y2);参数:x/y/z1~各点的x、y、z坐标2:返回值:两点之间的距离注意:需要 math.h源程序:float distance_2d(float x1,float x2,float y1,float y2){return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));}float distance_3d(float x1,float x2,float y1,float y2,float z1,float z2){return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2)));}5.射向法判断点是否在多边形内部语法:result=insidepolygon(Point *polygon,int N,Point p);参数:*polygon:多边形顶点数组N:多边形顶点个数p:被判断点返回值: 0:点在多边形内部;1:点在多边形外部注意:若p点在多边形顶点或者边上,返回值不确定,需另行判断需要 math.h源程序:#define MIN(x,y) (x < y ? x : y)#define MAX(x,y) (x > y ? x : y)typedef struct {double x,y;} Point;int insidepolygon(Point *polygon,int N,Point p){int counter = 0;int i;double x int ers;Point p1,p2;p1 = polygon[0];for (i=1;i<=N;i++) {p2 = polygon[i % N];if (p.y > MIN(p1.y,p2.y)) {if (p.y <= MAX(p1.y,p2.y)) {if (p.x <= MAX(p1.x,p2.x)) {if (p1.y != p2.y) {x int ers =(p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;if (p1.x == p2.x || p.x <= x int ers)counter++;}}}}p1 = p2;}if (counter % 2 == 0)return(OUTSIDE);elsereturn(INSIDE);}6.判断点是否在线段上语法:result=Pointonline(Point p1,Point p2,Point p);参数:p1、线段的两个端点p2:p:被判断点返回0:点在不在线段上;1:点在线段上值:注意:若p线段端点上返回1需要 math.h源程序:#define MIN(x,y) (x < y ? x : y)#define MAX(x,y) (x > y ? x : y)typedef struct {double x,y;} Point;int FC(double x1,double x2){if(x1-x2<0.000002&&x1-x2>-0.000002) return1; else return0;}int Pointonline(Point p1,Point p2,Point p){double x1,y1,x2,y2;x1=p.x-p1.x;x2=p2.x-p1.x;y1=p.y-p1.y;y2=p2.y-p1.y;if (FC(x1*y2-x2*y1,0)==0) return 0;if ((MIN(p1.x,p2.x)<=p.x&&p.x<=MAX(p1.x,p2.x))&&(MIN(p1.y,p2.y)<=p.y&&p.y<=MAX(p1.y,p2.y)))return 1; else return 0;}7.判断两线段是否相交语法:result=sectintersect(Point p1,Point p2,Point p3,Point p4);参数:p1两条线段的四个端点~4:返0:两线段不相交;1:两线段相交;2两线段首尾相接回值:注意:p1!=p2;p3!=p4;源程序:#define MIN(x,y) (x < y ? x : y)#define MAX(x,y) (x > y ? x : y)typedef struct {double x,y;} Point;int lineintersect(Point p1,Point p2,Point p3,Point p4){Point tp1,tp2,tp3;if((p1.x==p3.x&&p1.y==p3.y)||(p1.x==p4.x&&p1.y==p4.y)||(p2.x==p3.x&&p2.y==p3.y)||(p2.x==p4 .x&&p2.y==p4.y))return 2;//快速排斥试验if ((MIN(p1.x,p2.x)<p3.x&&p3.x<MAX(p1.x,p2.x)&&MIN(p1.y,p2.y)<p3.y<MAX(p1.y,p2.y))||(MIN(p1.x,p2.x)<p4.x&&p3.x<MAX(p1.x,p2.x)&&MIN(p1.y,p2.y)<p3.y<M AX(p1.y,p2.y)));else return 0;//跨立试验tp1.x=p1.x-p3.x;tp1.y=p1.y-p3.y;tp2.x=p4.x-p3.x;tp2.y=p4.y-p3.y;tp3.x=p2.x-p3.x;tp3.y=p2.y-p3.y;if ((tp1.x*tp2.y-tp1.y*tp2.x)*(tp2.x*tp3.y-tp2.y*tp3.x)>=0) return 1; else return 0;}8.判断线段与直线是否相交语法:result=lineintersect(Point p1,Point p2,Point p3,Point p4);参数:p1、p2:线段的两个端点p3、p4:直线上的两个点返回值: 0:线段直线不相交;1:线段和直线相交注意:如线段在直线上,返回 1源程序:typedef struct {double x,y;} Point;int lineintersect(Point p1,Point p2,Point p3,Point p4){Point tp1,tp2,tp3;tp1.x=p1.x-p3.x;tp1.y=p1.y-p3.y;tp2.x=p4.x-p3.x;tp2.y=p4.y-p3.y;tp3.x=p2.x-p3.x;tp3.y=p2.y-p3.y;if((tp1.x*tp2.y-tp1.y*tp2.x)*(tp2.x*tp3.y-tp2.y*tp3.x)>=0) return1; else return 0;}9.点到线段最短距离语法:result=mindistance(Point p1,Point p2,Point q);参数:p1、线段的两个端点p2:q:判断点返点q到线段p1p2的距离回值:注意:需要 math.h源程序:#define MIN(x,y) (x < y ? x : y)#define MAX(x,y) (x > y ? x : y)typedef struct {double x,y;} Point;double mindistance(Point p1,Point p2,Point q){int flag=1;double k;Point s;if (p1.x==p2.x) {s.x=p1.x;s.y=q.y;flag=0;}if (p1.y==p2.y) {s.x=q.x;s.y=p1.y;flag=0;}if (flag){k=(p2.y-p1.y)/(p2.x-p1.x);s.x=(k*k*p1.x+k*(q.y-p1.y)+q.x)/(k*k+1);s.y=k*(s.x-p1.x)+p1.y;}if (MIN(p1.x,p2.x)<=s.x&&s.x<=MAX(p1.x,p2.x))return sqrt((q.x-s.x)*(q.x-s.x)+(q.y-s.y)*(q.y-s.y));elsereturnMIN(sqrt((q.x-p1.x)*(q.x-p1.x)+(q.y-p1.y)*(q.y-p1.y)),sqrt((q.x-p2.x)*(q.x-p2.x)+(q.y-p2 .y)*(q.y-p2.y)));}10.求两直线的交点语法:result=mindistance(Point p1,Point p2,Point q);参数:p1直线上不相同的两点~p4:*p:通过指针返回结果返1:两直线相交;2:两直线平行回值:注意:如需要判断两线段交点,检验k和对应k1(注释中)的值是否在0~1之间,用在0~1之间的那个求交点源程序:typedef struct {double x,y;} Point;int linecorss(Point p1,Point p2,Point p3,Point p4,Point *p){double k;//同一直线if ((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x)==0&&(p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x)==0) return 2;//平行,不同一直线if ((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)==0) return 0;k=((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x) *(p2.y-p1.y));//k1=((p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3 .x)*(p2.y-p1.y));(*p).x=p1.x+k*(p2.x-p1.x);(*p).y=p1.y+k*(p2.y-p1.y);return 1;//有交点}11.判断一个封闭图形是凹集还是凸集语法:result=convex(Point *p,int n);参数:*p:封闭曲线顶点数组n:封闭曲线顶点个数返回值: 1:凸集;-1:凹集;0:曲线不符合要求无法计算注意:默认曲线为简单曲线:无交叉、无圈源程序:typedef struct {double x,y;} Point;int convex(Point *p,int n){int i,j,k;int flag = 0;double z;if (n < 3)return(0);for (i=0;i<n;i++) {j = (i + 1) % n;k = (i + 2) % n;z = (p[j].x - p[i].x) * (p[k].y - p[j].y);z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);if (z < 0)flag |= 1;else if (z > 0)flag |= 2;if (flag == 3)return-1; //CONCAVE}if (flag != 0)return 1; //CONVEXelsereturn 0;}12.Graham扫描法寻找凸包语法:Graham_scan(Point PointSet[],Point ch[],int n,int &len);参数:PointSe输入的点集t[]:ch[]:输出的凸包上的点集,按照逆时针方向排列n: PointSet中的点的数目len:输出的凸包上的点的个数返回值: null源程序:struct Point{float x,y;};float multiply(Point p1,Point p2,Point p0){return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));}float distance(Point p1,Point p2){return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));}void Graham_scan(Point PointSet[],Point ch[],int n,int &len){int i,j,k=0,top=2;Point tmp;for(i=1;i<n;i++)if((PointSet[i].y<PointSet[k].y)||((PointSet[i].y==PointSet[k].y)&&(PointSet[i].x<Poi ntSet[k].x)))k=i;tmp=PointSet[0];PointSet[0]=PointSet[k];PointSet[k]=tmp;for (i=1;i<n-1;i++){k=i;for (j=i+1;j<n;j++)if ( (multiply(PointSet[j],PointSet[k],PointSet[0])>0) ||((multiply(PointSet[j],PointSet[k],PointSe t[0])==0)&&(distance(PointSet[0],PointSet[ j])<distance(PointSet[0],PointSet[k]))) )k=j;tmp=PointSet[i];PointSet[i]=PointSet[k];PointSet[k]=tmp;}ch[0]=PointSet[0];ch[1]=PointSet[1];ch[2]=PointSet[2];for (i=3;i<n;i++){while (multiply(PointSet[i],ch[top],ch[top-1])>=0) top--;ch[++top]=PointSet[i];}len=top+1;}四、数论1.x的二进制长度语法:result=BitLength(int x);参数:x:测长的x返回值: x的二进制长度源程序:int BitLength(int x){int d = 0;while (x > 0) {x >>= 1;d++;}return d;}2.返回x的二进制表示中从低到高的第i位语法:result=BitAt(int x, int i);参数:x:十进制 xi:要求二进制的第i位返回值:返回x的二进制表示中从低到高的第i位注意:最低位为第一位源程序:int BitAt(int x, int i){return ( x & (1 << (i-1)) );}3.模取幂运算语法:result=Modular_Expoent(int a,int b,int n);参数:a、b、n: a^b mod n 的对应参数返回值: a^b mod n 的值注意:需要BitLength和BitAt源程序:int Modular_Expoent(int a,int b,int n){int i, y=1;for (i = BitLength(b); i > 0; i--){y = (y*y)%n;if (BitAt(b,i) > 0)y = (y*a)%n;}return y;}4.求解模线性方程语法:result=modular_equation(int a,int b,int n);参数:a、b、n: ax=b (mod n) 的对应参数返回值:方程的解源程序:int ext_euclid(int a,int b,int &x,int &y) //求gcd(a,b)=ax+by{int t,d;if (b==0) {x=1;y=0;return a;}d=ext_euclid(b,a %b,x,y);t=x;x=y;y=t-a/b*y;return d;}void modular_equation(int a,int b,int n){int e,i,d;int x,y;d=ext_euclid(a,n,x,y);if (b%d>0)printf("No answer!\n");else{e=(x*(b/d))%n;for (i=0;i<d;i++)printf("The %dth answeris : %ld\n",i+1,(e+i*(n/d))%n);}}5.求解模线性方程组(中国余数定理)语法:result=Modular_Expoent(int a,int b,int n);参数:B[]、W[]: a=B[] (mod W[]) 的对应参数返回值: a 的值注意:其中W[],B[]已知,W[i]>0且W[i]与W[j]互质, 求a源程序:int ext_euclid(int a,int b,int &x,int &y) //求gcd(a,b)=ax+by{int t,d;if (b==0) {x=1;y=0;return a;}d=ext_euclid(b,a %b,x,y);t=x;x=y;y=t-a/b*y;return d;}int China(int B[],int W[],int k){int i;int d,x,y,a=0,m,n=1;for (i=0;i<k;i++)n*=W[i];for (i=0;i<k;i++){m=n/W[i];d=ext_euclid(W[i],m,x,y);a=(a+y*m*B[i])%n;}if (a>0) return a;else return(a+n);}6.筛法素数产生器语法:result=prime(int a[],int n);参数:a[]:用于返回素数的数组n:产生n以内的素数,按升序放入a[]中返回值: n以内素数的个数注意:其中W[],B[]已知,W[i]>0且W[i]与W[j]互质, 求a 源程序:int prime(int a[],int n){int i,j,k,x,num,*b;n++;n/=2;b=(int *)malloc(sizeof(int)*(n+1)*2);a[0]=2;a[1]=3;num=2;for(i=1;i<=2*n;i++)b[i]=0;for(i=3;i<=n;i+=3)for(j=0;j<2;j++){x=2*(i+j)-1;while(b[x]==0){a[num++]=x;for(k=x;k<=2*n;k+=x)b[k]=1;}}return num;}7.判断一个数是否素数语法:result=comp(int n);参数:n:判断n是否素数返回值:素数返回1,否则返回0源程序:int comp(int n){int i,flag=1;for (i=2;i<=sqrt(n);i++)if (n%i==0) {flag=0;break;}if (flag==1) return 1; else return 0;}五、图论1.Prim算法求最小生成树语法:prim(Graph G,int vcount,int father[]);参数:G:图,用邻接矩阵表示vcount:表示图的顶点个数father[]:用来记录每个节点的父节点返回值: null注意:常数max_vertexes为图最大节点数常数infinity为无穷大源程序:#define infinity 1000000#define max_vertexes 5typedef int Graph[max_vertexes][max_vertexes];void prim(Graph G,int vcount,int father[]){int i,j,k;intlowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes];for (i=0;i<vcount;i++){lowcost[i]=G[0][i];closeset[i]=0;used[i]=0;father[i]=-1;}used[0]=1;for (i=1;i<vcount;i++){j=0;while (used[j]) j++;for (k=0;k<vcount;k++)if ((!used[k])&&(lowcost[k]<lowcost[j])) j=k;father[j]=closeset[j];used[j]=1;for (k=0;k<vcount;k++)if (!used[k]&&(G[j][k]<lowcost[k])){ lowcost[k]=G[j][k];closeset[k]=j; }}}2.Dijkstra算法求单源最短路径语法:result=Dijkstra(Graph G,int n,int s,int t, int path[]);参数:G:图,用邻接矩阵表示n:图的顶点个数s:开始节点t:目标节点path[]:用于返回由开始节点到目标节点的路径返回值:最短路径长度注意:输入的图的权必须非负顶点标号从0开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Dijkstra(Graph G,int n,int s,int t, int path[]){int i,j,w,minc,d[max_vertexes],mark[max_vertexes];for (i=0;i<n;i++) mark[i]=0;for (i=0;i<n;i++){ d[i]=G[s][i];path[i]=s; }mark[s]=1;path[s]=0;d[s]=0;for (i=1;i<n;i++){minc=infinity;w=0;for (j=0;j<n;j++)if ((mark[j]==0)&&(minc>=d[j])){minc=d[j];w=j;}mark[w]=1;for (j=0;j<n;j++)if((mark[j]==0)&&(G[w][j]!=infinity)&&(d[j]>d[w]+G[w][j])){ d[j]=d[w]+G[w][j];path[j]=w; }}return d[t];}3.Bellman-ford算法求单源最短路径语法:result=Bellman_ford(Graph G,int n,int s,int t,int path[],int success);参数:G:图,用邻接矩阵表示n:图的顶点个数s:开始节点t:目标节点path[]:用于返回由开始节点到目标节点的路径success:函数是否执行成功返回值:最短路径长度注意:输入的图的权可以为负,如果存在一个从源点可达的权为负的回路则success=0顶点标号从0开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Bellman_ford(Graph G,int n,int s,int t,int path[],int success){int i,j,k,d[max_vertexes];for (i=0;i<n;i++) {d[i]=infinity;path[i]=0;}d[s]=0;for (k=1;k<n;k++)for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]){d[j]=d[i]+G[i][j];path[j]=i;}success=0;for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]) return 0;success=1;return d[t];}4.Floyd-Warshall算法求每对节点间最短路径语法:Floyd_Washall(Graph G,int n,Graph D,Graph P);参数:G:图,用邻接矩阵表示n:图的顶点个数D: D[i,j]表示从i到j的最短距离P: P[i,j]表示从i到j的最短路径上j 的父节点返回null值:源程序:void Floyd_Washall(Graph G,int n,Graph D,Graph P){int i,j,k;for (i=0;i<n;i++)for (j=0;j<n;j++){ D[i][j]=G[i][j];P[i][j]=i; }for (i=0;i<n;i++) { D[i][i]=0;P[i][i]=0; }for (k=0;k<n;k++)for (i=0;i<n;i++)for (j=0;j<n;j++)if (D[i][j]>D[i][k]+D[k][j]){ D[i][j]=D[i][k]+D[k][j];P[i][j]=P[k][j]; } }六、排序/查找1.快速排序语法:quicksort(int l,int r,int b[]);参数:l:排序上界,开始时l=0r:排序下界,开始时r=数组元素个数b[]:被排序的元素返回值: null注意:输出升序序列源程序:void quicksort(int l,int r,int b[]){int i,j,x;if(l>=r) return;i=l;j=r;x=b[i];while(i!=j){while(b[j]>x&&j>i) j--;if(i<j){b[i]=b[j];i++;}while(b[i]<x&&j>i)i++;if(i<j){b[j]=b[i];j--;}}b[i]=x;quicksort(l,j-1,b);quicksort(i+1,r,b);}2.希尔排序语法:shellsort(int a[],int n);参数:n:数组元素个数a[]:待排序数组返回值: null注意:输出升序序列源程序:void shellsort(int a[],int n){int i,j,g;int temp,k;g=n/2;while(g!=0){for(i=g+1;i<=n;i++){temp=a[i];j=i-g;while(j>0){k=j+g;if(a[j]<=a[k])j=0;else{temp=a[j];a[j]=a[k];a[k]=temp;}j=j-g;}}g=g/2;}}3.选择法排序语法:sort(int t[],int n);参数:t[]:待排序数组n:数组t[]元素的个数返回值: null注意:输出升序序列小规模排序用源程序:void sort(int t[],int n){int i,j,k,temp;for (i=0;i<n;i++){k=i;for (j=i;j<n;j++) if (t[j]<t[k]) k=j;temp=t[i];t[i]=t[k];t[k]=temp;}}4.二分查找语法:result=search_bin(int *t,int k);参数:t[]:待查找数组k:查找关键字返回值:如果k在t[]中存在,输出i:t[i]=k,否则输出-1注意:要求查找数组是有序升序序列源程序:int search_bin(int *t,int k){int low=1,high=10,mid;while (low<=high){mid=(low+high)/2;if (k==t[mid]) return mid;else if (k<t[mid]) high=mid-1;else low=mid+1;}return -1;}七、数据结构1.顺序队列源程序:#define maxsize 100typedef struct{int data[maxsize];int front;int rear;} sqqueue;int sqinit(sqqueue *p) //队列初始化{p->front=0;p->rear=0;return 1;}int enqueue(sqqueue *q, int e) //入队{if((q->rear+1)%maxsize==q->front)return 0;elseq->data[q->rear]=e;q->rear=(q->rear+1)%maxsize;return 1;}int dequeue(sqqueue *q) //出队{。

相关文档
最新文档