经典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程序设计常用算法与数据结构参考汇总
A C M程序设计常用算法与数据结构参考ACM程序设计常用算法与数据结构参考Tomsdinary目录前言 (7)排序算法 (8)插入排序 (8)选择排序 (10)冒泡排序 (11)希尔排序 (12)随机化快速排序 (14)归并排序 (18)堆排序 (19)大整数处理 (22)包含头文件 (22)定义 (22)实现 (24)流输出 (24)流输入 (24)赋值 (25)转换函数 (26)规范化符号化 (26)带符号乘法 (27)无符号取模 (27)整数乘法 (28)整数加法 (30)带符号加法 (32)浮点乘法 (33)浮点加法 (35)带符号减法 (36)整数减法 (37)浮点减法 (40)带符号比较 (41)无符号比较 (42)无符号乘方 (43)带符号乘方 (43)使用方法 (44)高级数据结构 (44)普通二叉搜素树 (44)包含头文件 (44)定义 (44)实现 (47)删树 (50)插入元素到树 (50)复制树 (53)求树的高度 (56)删除元素 (57)使用方法 (59)基本线段树模式 (60)基本并查集模式 (62)散列实现的一种方式参考 (63)定义与实现 (63)使用方法 (72)堆 (72)包含头文件 (72)定义与实现 (73)使用方法 (75)图相关算法 (76)图的深度优先和广度优先算法举例 (76)无向图最小生成树的Kruskal算法举例 (78)无向图最小生成树的Prim算法举例 (80)有向图的单源最短路径Dijkstra算法举例 (82)有向图的多源最短路径Floyd算法举例 (84)拓扑排序举例 (85)AOE网的算法举例 (88)求图的一个中心算法举例 (92)求图的P个中心算法举例 (95)SPFA算法举例 (99)割顶和块的算法举例 (102)计算几何算法 (105)向量模 (105)向量点积 (105)向量叉积 (105)左右判断 (106)相交判断 (106)正规相交交点 (106)判断多边形凸 (107)任意多变形面积 (107)凸包问题的快包实现举例 (108)STL算法参考 (113)accumulate() (113)adjacent_difference() (113)adjacent_find() (114)binary_search() (114)copy() (115)copy_backward() (115)count() (116)count_if() (116)equal() (116)fill() (118)fill_n() (118)find() (118)find_if() (118)find_end() (119)find_first_of() (119)for_each() (120)generate() (120)generate_n() (120)includes() (121)inner_product() (121)inplace_merge() (122)iter_swap() (122)lexicographical_compare() (123)lower_bound() (124)max() (124)max_element() (125)min() (125)min_element() (125)merge() (126)mismatch() (126)next_permutation() (127)nnth_element() (127)partial_sort() (128)partial_sort_copy() (129)partial_sum() (129)prev_permutation() (130)random_shuffle() (130)remove() (131)remove_copy() (132)remove_if() (132)remove_copy_if() (132)replace() (133)replace_copy() (133)replace_if() (133)replace_copy_if() (133)reverse() (134)reverse_copy() (134)rotate() (134)rotate_copy() (135)search() (135)search_n() (135)set_difference() (136)set_symmetric_difference() (137)set_union() (138)sort() (138)stable_partition() (139)stable_sort() (139)swap() (140)swap_range() (140)transform() (140)unique() (141)unique_copy() (142)upper_bound() (142)make_heap() (143)pop_heap() (143)push_heap() (144)sort_heap() (144)字符串处理 (145)KMP算法举例 (145)C++语言可用头文件 (147)<algorithm> (147)<bitset> (147)<complex> (147)<deque> (147)<exception> (147)<fstream> (147)<functional> (147)<iomanip> (148)<ios> (148)<iosfwd> (148)<iostream> (148)<iso646.h> (148)<istream> (148)<iterator> (148)<limits> (149)<list> (149)<locale> (149)<map> (149)<memory> (149)<new> (149)<numeric> (149)<ostream> (150)<queue> (150)<set> (150)<sstream> (150)<stdexcept> (150)<streambuf> (150)<string> (151)<strstream> (151)<utility> (151)<valarray> (151)<vector> (151)<cassert> (151)<cctype> (151)<cerrno> (151)<cfloat> (152)<ciso646> (152)<climits> (152)<clocale> (152)<cmath> (152)<csetjmp> (152)<csignal> (152)<cstdarg> (152)<cstddef> (152)<cstdio> (153)<cstdlib> (153)<cstring> (153)<ctime> (153)<cwchar> (153)<cwctype> (153)前言如今的程序设计已不再是个人英雄时代了,程序的设计和开发实施需要靠团队成员的积极配合和合作。
ACM经典代码
目录一.数论 (3)1.阶乘最后非零位 (3)2. 模线性方程(组) (4)3. 素数表 (6)4. 素数随机判定(miller_rabin) (6)5. 质因数分解 (7)6. 最大公约数欧拉函数 (8)二.图论_匹配 (9)1. 二分图最大匹配(hungary邻接表形式) (9)2. 二分图最大匹配(hungary邻接表形式,邻接阵接口) (10)3. 二分图最大匹配(hungary邻接阵形式) (10)4. 二分图最大匹配(hungary正向表形式) (11)5. 二分图最佳匹配(kuhn_munkras邻接阵形式) (11)6. 一般图匹配(邻接表形式) (12)7. 一般图匹配(邻接表形式,邻接阵接口) (13)8. 一般图匹配(邻接阵形式) (14)9. 一般图匹配(正向表形式) (15)三.图论_生成树 (16)1. 最小生成树(kruskal邻接表形式) (16)2. 最小生成树(kruskal正向表形式) (17)3. 最小生成树(prim+binary_heap邻接表形式) (19)4. 最小生成树(prim+binary_heap正向表形式) (20)5. 最小生成树(prim+mapped_heap邻接表形式) (21)6. 最小生成树(prim+mapped_heap正向表形式) (22)7. 最小生成树(prim邻接阵形式) (24)8. 最小树形图(邻接阵形式) (24)四.图论_网络流 (26)1. 上下界最大流(邻接表形式) (26)2. 上下界最大流(邻接阵形式) (27)3. 上下界最小流(邻接表形式) (28)4. 上下界最小流(邻接阵形式) (30)5. 最大流(邻接表形式) (31)6. 最大流(邻接表形式,邻接阵接口) (32)7. 最大流(邻接阵形式) (33)8. 最大流无流量(邻接阵形式) (34)9. 最小费用最大流(邻接阵形式) (34)五. 图论_最短路径 (35)1. 最短路径(单源bellman_ford邻接阵形式) (35)2. 最短路径(单源dijkstra_bfs邻接表形式) (36)3. 最短路径(单源dijkstra_bfs正向表形式) (37)4. 最短路径(单源dijkstra+binary_heap邻接表形式) (37)5. 最短路径(单源dijkstra+binary_heap正向表形式) (38)6. 最短路径(单源dijkstra+mapped_heap邻接表形式) (40)7. 最短路径(单源dijkstra+mapped_heap正向表形式) (41)8. 最短路径(单源dijkstra邻接阵形式) (42)9. 最短路径(多源floyd_warshall邻接阵形式) (43)六. 图论_连通性 (43)1. 无向图关键边(dfs邻接阵形式) (43)2. 无向图关键点(dfs邻接阵形式) (44)3. 无向图块(bfs邻接阵形式) (45)4. 无向图连通分支(bfs邻接阵形式) (46)5. 无向图连通分支(dfs邻接阵形式) (46)6. 有向图强连通分支(bfs邻接阵形式) (47)7. 有向图强连通分支(dfs邻接阵形式) (48)8. 有向图最小点基(邻接阵形式) (49)七. 图论_应用 (49)1.欧拉回路(邻接阵形式) (49)2. 前序表转化 (50)3. 树的优化算法 (50)4. 拓扑排序(邻接阵形式). (52)5. 最佳边割集 (52)6. 最佳顶点割集 (54)7. 最小边割集 (55)8. 最小顶点割集 (56)9. 最小路径覆盖 (57)八. 图论_NP搜索 (58)1. 最大团(n小于64)(faster) (58)2. 最大团 (61)九. 组合 (62)1. 排列组合生成 (62)2. 生成gray码 (63)3. 置换(polya) (64)4. 字典序全排列 (64)5. 字典序组合 (65)6. 组合公式 (65)十. 数值计算 (66)1. 定积分计算(Romberg) (66)2. 多项式求根(牛顿法) (67)3. 周期性方程(追赶法) (69)十一. 几何 (70)1. 多边形 (70)2. 多边形切割 (73)3. 浮点函数 (74)4. 几何公式 (80)5. 面积 (82)6. 球面 (83)7. 三角形 (83)8. 三维几何 (86)9. 凸包(graham) (95)10. 网格(pick) (98)11. 圆 (98)12. 整数函数 (100)13. 注意 (103)十二. 结构 (104)1. 并查集 (104)2. 并查集扩展(friend_enemy) (104)3. 堆(binary) (105)4. 堆(mapped) (105)5. 矩形切割 (106)6. 线段树 (107)7. 线段树扩展 (109)8. 线段树应用 (111)9. 子段和 (112)10. 子阵和 (112)十三. 其他 (113)1. 分数 (113)2. 矩阵 (115)3. 日期 (117)4. 线性方程组(gauss) (119)5. 线性相关 (120)十四. 应用 (121)1. joseph (121)2. N皇后构造解 (122)3. 布尔母函数 (123)4. 第k元素 (123)5. 幻方构造 (124)6. 模式匹配(kmp) (125)7. 逆序对数 (125)8. 字符串最小表示 (126)9. 最长公共单调子序列 (126)10. 最长子序列 (128)11. 最大子串匹配 (129)12. 最大子段和 (130)13. 最大子阵和 (130)一.数论1.阶乘最后非零位//求阶乘最后非零位,复杂度O(nlogn)//返回该位,n以字符串方式传入#include <string.h>#define MAXN 10000int lastdigit(char* buf){const int mod[20]={1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2};int len=strlen(buf),a[MAXN],i,c,ret=1;if (len==1)return mod[buf[0]-'0'];for (i=0;i<len;i++)a[i]=buf[len-1-i]-'0';for (;len;len-=!a[len-1]){ret=ret*mod[a[1]%2*10+a[0]]%5;for (c=0,i=len-1;i>=0;i--)c=c*10+a[i],a[i]=c/5,c%=5;}return ret+ret%2*5;}2. 模线性方程(组)#ifdef WIN32typedef __int64 i64;#elsetypedef long long i64;#endif//扩展Euclid求解gcd(a,b)=ax+byint ext_gcd(int a,int b,int& x,int& y){int t,ret;if (!b){x=1,y=0;return a;}ret=ext_gcd(b,a%b,x,y);t=x,x=y,y=t-a/b*y;return ret;}//计算m^a, O(loga), 本身没什么用, 注意这个按位处理的方法 :-Pint exponent(int m,int a){int ret=1;for (;a;a>>=1,m*=m)if (a&1)ret*=m;return ret;}//计算幂取模a^b mod n, O(logb)int modular_exponent(int a,int b,int n){ //a^b mod n int ret=1;for (;b;b>>=1,a=(int)((i64)a)*a%n)if (b&1)ret=(int)((i64)ret)*a%n;return ret;}//求解模线性方程ax=b (mod n)//返回解的个数,解保存在sol[]中//要求n>0,解的范围0..n-1int modular_linear(int a,int b,int n,int* sol){int d,e,x,y,i;d=ext_gcd(a,n,x,y);if (b%d)return 0;e=(x*(b/d)%n+n)%n;for (i=0;i<d;i++)sol[i]=(e+i*(n/d))%n;return d;}//求解模线性方程组(中国余数定理)// x = b[0] (mod w[0])// x = b[1] (mod w[1])// ...// x = b[k-1] (mod w[k-1])//要求w[i]>0,w[i]与w[j]互质,解的范围1..n,n=w[0]*w[1]*...*w[k-1] int modular_linear_system(int b[],int w[],int k){int d,x,y,a=0,m,n=1,i;for (i=0;i<k;i++)n*=w[i];for (i=0;i<k;i++){m=n/w[i];d=ext_gcd(w[i],m,x,y);a=(a+y*m*b[i])%n;}return (a+n)%n;}3. 素数表//用素数表判定素数,先调用initprimeint plist[10000],pcount=0;int prime(int n){int i;if((n!=2&&!(n%2))||(n!=3&&!(n%3))||(n!=5&&!(n%5))||(n!=7&&!(n%7))) return 0;for (i=0;plist[i]*plist[i]<=n;i++)if (!(n%plist[i]))return 0;return n>1;}void initprime(){int i;for (plist[pcount++]=2,i=3;i<50000;i++)if (prime(i))plist[pcount++]=i;}4. 素数随机判定(miller_rabin)//miller rabin//判断自然数n是否为素数//time越高失败概率越低,一般取10到50#include <stdlib.h>#ifdef WIN32typedef __int64 i64;#elsetypedef long long i64;#endifint modular_exponent(int a,int b,int n){ //a^b mod n int ret;for (;b;b>>=1,a=(int)((i64)a)*a%n)if (b&1)ret=(int)((i64)ret)*a%n;return ret;}// Carmicheal number: 561,41041,825265,321197185int miller_rabin(int n,int time=10){if(n==1||(n!=2&&!(n%2))||(n!=3&&!(n%3))||(n!=5&&!(n%5))||(n!=7&&!(n %7)))return 0;while (time--)if(modular_exponent(((rand()&0x7fff<<16)+rand()&0x7fff+rand()&0x7ff f)%(n-1)+1,n-1,n)!=1)return 0;return 1;}5. 质因数分解//分解质因数//prime_factor()传入n, 返回不同质因数的个数//f存放质因数,nf存放对应质因数的个数//先调用initprime(),其中第二个initprime()更快#include<iostream>#include<cstdio>#include<cmath>using namespace std;#define MAXN 2001000#define PSIZE 100000int plist[PSIZE], pcount=0;int prime(int n){int i;if((n!=2&&!(n%2))||(n!=3&&!(n%3))||(n!=5&&!(n%5))||(n!=7&&!(n%7))) return 0;for (i=0;plist[i]*plist[i]<=n;++i)if (!(n%plist[i]))return 0;return n>1;}void initprime(){int i;for (plist[pcount++]=2,i=3;i<100000;++i)if (prime(i))plist[pcount++]=i;}int prime_factor(int n, int* f, int *nf) {int cnt = 0;int n2 = sqrt((double)n);for(int i = 0; n > 1 && plist[i] <= n2; ++i)if (n % plist[i] == 0) {for (nf[cnt] = 0; n % plist[i] == 0; ++nf[cnt], n /= plist[i]);f[cnt++] = plist[i];}if (n > 1) nf[cnt] = 1, f[cnt++] = n;return cnt;}/*//产生MAXN以内的所有素数//note:2863311530就是10101010101010101010101010101010//给所有2的倍数赋初值#include <cmath>#include <iostream>using namespace std;#define MAXN 100000000unsigned int plist[6000000],pcount;unsigned int isprime[(MAXN>>5)+1];#define setbitzero(a) (isprime[(a)>>5]&=(~(1<<((a)&31))))#define setbitone(a) (isprime[(a)>>5]|=(1<<((a)&31)))#define ISPRIME(a) (isprime[(a)>>5]&(1<<((a)&31)))void initprime(){int i,j,m;int t=(MAXN>>5)+1;for(i=0;i<t;++i)isprime[i]=2863311530;plist[0]=2;setbitone(2);setbitzero(1);m=(int)sqrt(MAXN);for(pcount=1,i=3;i<=m;i+=2)if(ISPRIME(i))for(plist[pcount++]=i,j=i<<1;j<=MAXN;j+=i)setbitzero(j);if(!(i&1))++i;for(;i<=MAXN;i+=2)if(ISPRIME(i))plist[pcount++]=i;}6. 最大公约数欧拉函数int gcd(int a,int b){return b?gcd(b,a%b):a;}inline int lcm(int a,int b){return a/gcd(a,b)*b;//求1..n-1中与n互质的数的个数int eular(int n){int ret=1,i;for (i=2;i*i<=n;i++)if (n%i==0){n/=i,ret*=i-1;while (n%i==0)n/=i,ret*=i;}if (n>1)ret*=n-1;return ret;}二.图论_匹配1. 二分图最大匹配(hungary邻接表形式)//二分图最大匹配,hungary算法,邻接表形式,复杂度O(m*e)//返回最大匹配数,传入二分图大小m,n和邻接表list(只需一边)//match1,match2返回一个最大匹配,未匹配顶点match值为-1#include <string.h>#define MAXN 310#define _clr(x) memset(x,0xff,sizeof(int)*MAXN)struct edge_t{int from,to;edge_t* next;};int hungary(int m,int n,edge_t* list[],int* match1,int* match2){ int s[MAXN],t[MAXN],p,q,ret=0,i,j,k;edge_t* e;for (_clr(match1),_clr(match2),i=0;i<m;ret+=(match1[i++]>=0)) for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)for (e=list[k=s[p]];e&&match1[i]<0;e=e->next)if (t[j=e->to]<0){s[++q]=match2[j],t[j]=k;if (s[q]<0)for (p=j;p>=0;j=p)match2[j]=k=t[j],p=match1[k],match1[k]=j;}return ret;2. 二分图最大匹配(hungary邻接表形式,邻接阵接口)//二分图最大匹配,hungary算法,邻接表形式,邻接阵接口,复杂度O(m*e)s//返回最大匹配数,传入二分图大小m,n和邻接阵//match1,match2返回一个最大匹配,未匹配顶点match值为-1#include <string.h>#include <vector>#define MAXN 310#define _clr(x) memset(x,0xff,sizeof(int)*MAXN)int hungary(int m,int n,int mat[][MAXN],int* match1,int* match2){ int s[MAXN],t[MAXN],p,q,ret=0,i,j,k,r;vector<int> e[MAXN];//生成邻接表(只需一边)for(i=0;i<m;++i)for(j=0;j<n;++j)if (mat[i][j]) e[i].push_back(j);for (_clr(match1),_clr(match2),i=0;i<m;ret+=(match1[i++]>=0)) for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)for(r=0,k=s[p];r<e[k].size()&&match1[i]<0;++r)if (t[j=e[k][r]]<0){s[++q]=match2[j],t[j]=k;if (s[q]<0)for (p=j;p>=0;j=p)match2[j]=k=t[j],p=match1[k],match1[k]=j;}return ret;}3. 二分图最大匹配(hungary邻接阵形式)//二分图最大匹配,hungary算法,邻接阵形式,复杂度O(m*m*n)//返回最大匹配数,传入二分图大小m,n和邻接阵mat,非零元素表示有边//match1,match2返回一个最大匹配,未匹配顶点match值为-1#include <string.h>#define MAXN 310#define _clr(x) memset(x,0xff,sizeof(int)*MAXN)int hungary(int m,int n,int mat[][MAXN],int* match1,int* match2){ int s[MAXN],t[MAXN],p,q,ret=0,i,j,k;for (_clr(match1),_clr(match2),i=0;i<m;ret+=(match1[i++]>=0)) for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)for (k=s[p],j=0;j<n&&match1[i]<0;j++)if (mat[k][j]&&t[j]<0){s[++q]=match2[j],t[j]=k;if (s[q]<0)for (p=j;p>=0;j=p)match2[j]=k=t[j],p=match1[k],match1[k]=j;}return ret;}4. 二分图最大匹配(hungary正向表形式)//二分图最大匹配,hungary算法,正向表形式,复杂度O(m*e)//返回最大匹配数,传入二分图大小m,n和正向表list,buf(只需一边)//match1,match2返回一个最大匹配,未匹配顶点match值为-1#include <string.h>#define MAXN 310#define _clr(x) memset(x,0xff,sizeof(int)*MAXN)int hungary(int m,int n,int* list,int* buf,int* match1,int* match2){ int s[MAXN],t[MAXN],p,q,ret=0,i,j,k,l;for (_clr(match1),_clr(match2),i=0;i<m;ret+=(match1[i++]>=0)) for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)for (l=list[k=s[p]];l<list[k+1]&&match1[i]<0;l++)if (t[j=buf[l]]<0){s[++q]=match2[j],t[j]=k;if (s[q]<0)for (p=j;p>=0;j=p)match2[j]=k=t[j],p=match1[k],match1[k]=j;}return ret;}5. 二分图最佳匹配(kuhn_munkras邻接阵形式)//二分图最佳匹配,kuhn munkras算法,邻接阵形式,复杂度O(m*m*n)//返回最佳匹配值,传入二分图大小m,n和邻接阵mat,表示权值//match1,match2返回一个最佳匹配,未匹配顶点match值为-1//一定注意m<=n,否则循环无法终止//最小权匹配可将权值取相反数#include <string.h>#define MAXN 310#define inf 1000000000#define _clr(x) memset(x,0xff,sizeof(int)*n)int kuhn_munkras(int m,int n,int mat[][MAXN],int* match1,int* match2){int s[MAXN],t[MAXN],l1[MAXN],l2[MAXN],p,q,ret=0,i,j,k;for (i=0;i<m;i++)for (l1[i]=-inf,j=0;j<n;j++)l1[i]=mat[i][j]>l1[i]?mat[i][j]:l1[i];for (i=0;i<n;l2[i++]=0);for (_clr(match1),_clr(match2),i=0;i<m;i++){for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)for (k=s[p],j=0;j<n&&match1[i]<0;j++)if (l1[k]+l2[j]==mat[k][j]&&t[j]<0){s[++q]=match2[j],t[j]=k;if (s[q]<0)for (p=j;p>=0;j=p)match2[j]=k=t[j],p=match1[k],match1[k]=j;}if (match1[i]<0){for (i--,p=inf,k=0;k<=q;k++)for (j=0;j<n;j++)if (t[j]<0&&l1[s[k]]+l2[j]-mat[s[k]][j]<p)p=l1[s[k]]+l2[j]-mat[s[k]][j];for (j=0;j<n;l2[j]+=t[j]<0?0:p,j++);for (k=0;k<=q;l1[s[k++]]-=p);}}for (i=0;i<m;i++)ret+=mat[i][match1[i]];return ret;}6. 一般图匹配(邻接表形式)//一般图最大匹配,邻接表形式,复杂度O(n*e)//返回匹配顶点对数,match返回匹配,未匹配顶点match值为-1//传入图的顶点数n和邻接表list#define MAXN 100struct edge_t{int from,to;edge_t* next;};int aug(int n,edge_t* list[],int* match,int* v,int now){ int t,ret=0;edge_t* e;v[now]=1;for (e=list[now];e;e=e->next)if (!v[t=e->to]){if (match[t]<0)match[now]=t,match[t]=now,ret=1;else{v[t]=1;if (aug(n,list,match,v,match[t]))match[now]=t,match[t]=now,ret=1;v[t]=0;}if (ret)break;}v[now]=0;return ret;}int graph_match(int n,edge_t* list[],int* match){ int v[MAXN],i,j;for (i=0;i<n;i++)v[i]=0,match[i]=-1;for (i=0,j=n;i<n&&j>=2;)if (match[i]<0&&aug(n,list,match,v,i))i=0,j-=2;elsei++;for (i=j=0;i<n;i++)j+=(match[i]>=0);return j/2;}7. 一般图匹配(邻接表形式,邻接阵接口)//一般图最大匹配,邻接表形式,复杂度O(n*e)//返回匹配顶点对数,match返回匹配,未匹配顶点match值为-1//传入图的顶点数n和邻接表list#include <vector>#define MAXN 100int aug(int n,vector<int> list[],int* match,int* v,int now){ int t,ret=0,r;v[now]=1;// for (e=list[now];e;e=e->next)for (r=0;r<list[now].size();++r)if (!v[t=list[now][r]]){if (match[t]<0)match[now]=t,match[t]=now,ret=1;else{if (aug(n,list,match,v,match[t]))match[now]=t,match[t]=now,ret=1;v[t]=0;}if (ret)break;}v[now]=0;return ret;}int graph_match(int n,int mat[][MAXN],int* match){ int v[MAXN],i,j;vector<int> list[MAXN];for (i=0;i<n;i++)for (j=0;j<n;j++)if (mat[i][j]) list[i].push_back(j);for (i=0;i<n;i++)v[i]=0,match[i]=-1;for (i=0,j=n;i<n&&j>=2;)if (match[i]<0&&aug(n,list,match,v,i))i=0,j-=2;elsei++;for (i=j=0;i<n;i++)j+=(match[i]>=0);return j/2;}8. 一般图匹配(邻接阵形式)//一般图最大匹配,邻接阵形式,复杂度O(n^3)//返回匹配顶点对数,match返回匹配,未匹配顶点match值为-1//传入图的顶点数n和邻接阵mat#define MAXN 100int aug(int n,int mat[][MAXN],int* match,int* v,int now){ int i,ret=0;v[now]=1;for (i=0;i<n;i++)if (!v[i]&&mat[now][i]){if (match[i]<0)match[now]=i,match[i]=now,ret=1;else{if (aug(n,mat,match,v,match[i]))match[now]=i,match[i]=now,ret=1;v[i]=0;}if (ret)break;}v[now]=0;return ret;}int graph_match(int n,int mat[][MAXN],int* match){ int v[MAXN],i,j;for (i=0;i<n;i++)v[i]=0,match[i]=-1;for (i=0,j=n;i<n&&j>=2;)if (match[i]<0&&aug(n,mat,match,v,i))i=0,j-=2;elsei++;for (i=j=0;i<n;i++)j+=(match[i]>=0);return j/2;}9. 一般图匹配(正向表形式)//一般图最大匹配,正向表形式,复杂度O(n*e)//返回匹配顶点对数,match返回匹配,未匹配顶点match值为-1//传入图的顶点数n和正向表list,buf#define MAXN 100int aug(int n,int* list,int* buf,int* match,int* v,int now){ int i,t,ret=0;v[now]=1;for (i=list[now];i<list[now+1];i++)if (!v[t=buf[i]]){if (match[t]<0)match[now]=t,match[t]=now,ret=1;else{v[t]=1;if (aug(n,list,buf,match,v,match[t]))match[now]=t,match[t]=now,ret=1;v[t]=0;}if (ret)break;}v[now]=0;return ret;}int graph_match(int n,int* list,int* buf,int* match){ int v[MAXN],i,j;for (i=0;i<n;i++)v[i]=0,match[i]=-1;for (i=0,j=n;i<n&&j>=2;)if (match[i]<0&&aug(n,list,buf,match,v,i))i=0,j-=2;elsei++;for (i=j=0;i<n;i++)j+=(match[i]>=0);return j/2;}三.图论_生成树1. 最小生成树(kruskal邻接表形式)//无向图最小生成树,kruskal算法,邻接表形式,复杂度O(mlogm)//返回最小生成树的长度,传入图的大小n和邻接表list//可更改边权的类型,edge[][2]返回树的构造,用边集表示//如果图不连通,则对各连通分支构造最小生成树,返回总长度#include <string.h>#define MAXN 200#define inf 1000000000typedef double elem_t;struct edge_t{int from,to;elem_t len;edge_t* next;};#define _ufind_run(x) for(;p[t=x];x=p[x],p[t]=(p[x]?p[x]:x)) #define _run_both _ufind_run(i);_ufind_run(j)struct ufind{int p[MAXN],t;void init(){memset(p,0,sizeof(p));}void set_friend(int i,int j){_run_both;p[i]=(i==j?0:j);}int is_friend(int i,int j){_run_both;return i==j&&i;}};#define _cp(a,b) ((a).len<(b).len)struct heap_t{int a,b;elem_t len;};struct minheap{heap_t h[MAXN*MAXN];int n,p,c;void init(){n=0;}void ins(heap_t e){for (p=++n;p>1&&_cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1);h[p]=e;}int del(heap_t& e){if (!n) return 0;for(e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[p] =h[c],p=c,c<<=1);h[p]=h[n--];return 1;}};elem_t kruskal(int n,edge_t* list[],int edge[][2]){ufind u;minheap h;edge_t* t;heap_t e;elem_t ret=0;int i,m=0;u.init(),h.init();for (i=0;i<n;i++)for (t=list[i];t;t=t->next)if (i<t->to)e.a=i,e.b=t->to,e.len=t->len,h.ins(e);while (m<n-1&&h.del(e))if (!u.is_friend(e.a+1,e.b+1))edge[m][0]=e.a,edge[m][1]=e.b,ret+=e.len,u.set_friend(e.a+1,e. b+1);return ret;}2. 最小生成树(kruskal正向表形式)//无向图最小生成树,kruskal算法,正向表形式,复杂度O(mlogm)//返回最小生成树的长度,传入图的大小n和正向表list,buf//可更改边权的类型,edge[][2]返回树的构造,用边集表示//如果图不连通,则对各连通分支构造最小生成树,返回总长度#include <string.h>#define MAXN 200#define inf 1000000000typedef double elem_t;struct edge_t{int to;elem_t len;};#define _ufind_run(x) for(;p[t=x];x=p[x],p[t]=(p[x]?p[x]:x))#define _run_both _ufind_run(i);_ufind_run(j)struct ufind{int p[MAXN],t;void init(){memset(p,0,sizeof(p));}void set_friend(int i,int j){_run_both;p[i]=(i==j?0:j);}int is_friend(int i,int j){_run_both;return i==j&&i;}};#define _cp(a,b) ((a).len<(b).len)struct heap_t{int a,b;elem_t len;};struct minheap{heap_t h[MAXN*MAXN];int n,p,c;void init(){n=0;}void ins(heap_t e){for (p=++n;p>1&&_cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1);h[p]=e;}int del(heap_t& e){if (!n) return 0;for(e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[p] =h[c],p=c,c<<=1);h[p]=h[n--];return 1;}};elem_t kruskal(int n,int* list,edge_t* buf,int edge[][2]){ ufind u;minheap h;heap_t e;elem_t ret=0;int i,j,m=0;u.init(),h.init();for (i=0;i<n;i++)for (j=list[i];j<list[i+1];j++)if (i<buf[j].to)e.a=i,e.b=buf[j].to,e.len=buf[j].len,h.ins(e);while (m<n-1&&h.del(e))if (!u.is_friend(e.a+1,e.b+1))edge[m][0]=e.a,edge[m][1]=e.b,ret+=e.len,u.set_friend(e.a+1,e. b+1);return ret;}3. 最小生成树(prim+binary_heap邻接表形式)//无向图最小生成树,prim算法+二分堆,邻接表形式,复杂度O(mlogm)//返回最小生成树的长度,传入图的大小n和邻接表list//可更改边权的类型,pre[]返回树的构造,用父结点表示,根节点(第一个)pre值为-1 //必须保证图的连通的!#define MAXN 200#define inf 1000000000typedef double elem_t;struct edge_t{int from,to;elem_t len;edge_t* next;};#define _cp(a,b) ((a).d<(b).d)struct heap_t{elem_t d;int v;};struct heap{heap_t h[MAXN*MAXN];int n,p,c;void init(){n=0;}void ins(heap_t e){for (p=++n;p>1&&_cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1);h[p]=e;}int del(heap_t& e){if (!n) return 0;for(e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[p] =h[c],p=c,c<<=1);h[p]=h[n--];return 1;}};elem_t prim(int n,edge_t* list[],int* pre){heap h;elem_t min[MAXN],ret=0;edge_t* t;heap_t e;int v[MAXN],i;for (i=0;i<n;i++)min[i]=inf,v[i]=0,pre[i]=-1;h.init();e.v=0,e.d=0,h.ins(e);while (h.del(e))if (!v[e.v])for (v[e.v]=1,ret+=e.d,t=list[e.v];t;t=t->next)if (!v[t->to]&&t->len<min[t->to])pre[t->to]=t->from,min[e.v=t->to]=e.d=t->len,h.ins(e);return ret;}4. 最小生成树(prim+binary_heap正向表形式)//无向图最小生成树,prim算法+二分堆,正向表形式,复杂度O(mlogm)//返回最小生成树的长度,传入图的大小n和正向表list,buf//可更改边权的类型,pre[]返回树的构造,用父结点表示,根节点(第一个)pre值为-1 //必须保证图的连通的!#define MAXN 200#define inf 1000000000typedef double elem_t;struct edge_t{int to;elem_t len;};#define _cp(a,b) ((a).d<(b).d)struct heap_t{elem_t d;int v;};struct heap{heap_t h[MAXN*MAXN];int n,p,c;void init(){n=0;}void ins(heap_t e){for (p=++n;p>1&&_cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1);h[p]=e;}int del(heap_t& e){if (!n) return 0;for(e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[p] =h[c],p=c,c<<=1);h[p]=h[n--];return 1;}};elem_t prim(int n,int* list,edge_t* buf,int* pre){heap h;heap_t e;elem_t min[MAXN],ret=0;int v[MAXN],i,j;for (i=0;i<n;i++)min[i]=inf,v[i]=0,pre[i]=-1;h.init();e.v=0,e.d=0,h.ins(e);while (h.del(e))if (!v[i=e.v])for (v[i]=1,ret+=e.d,j=list[i];j<list[i+1];j++)if (!v[buf[j].to]&&buf[j].len<min[buf[j].to])pre[buf[j].to]=i,min[e.v=buf[j].to]=e.d=buf[j].len,h.ins(e);return ret;}5. 最小生成树(prim+mapped_heap邻接表形式)//无向图最小生成树,prim算法+映射二分堆,邻接表形式,复杂度O(mlogn)//返回最小生成树的长度,传入图的大小n和邻接表list//可更改边权的类型,pre[]返回树的构造,用父结点表示,根节点(第一个)pre值为-1 //必须保证图的连通的!#define MAXN 200#define inf 1000000000typedef double elem_t;struct edge_t{int from,to;elem_t len;edge_t* next;};#define _cp(a,b) ((a)<(b))struct heap{elem_t h[MAXN+1];int ind[MAXN+1],map[MAXN+1],n,p,c;void init(){n=0;}void ins(int i,elem_t e){for(p=++n;p>1&&_cp(e,h[p>>1]);h[map[ind[p]=ind[p>>1]]=p]=h[p>>1],p>> =1);h[map[ind[p]=i]=p]=e;}int del(int i,elem_t& e){i=map[i];if (i<1||i>n) return 0;for(e=h[p=i];p>1;h[map[ind[p]=ind[p>>1]]=p]=h[p>>1],p>>=1);for(c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[map[ind[p]= ind[c]]=p]=h[c],p=c,c<<=1);h[map[ind[p]=ind[n]]=p]=h[n];n--;return 1;}int delmin(int& i,elem_t& e){if (n<1) return 0;i=ind[1];for(e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[ma p[ind[p]=ind[c]]=p]=h[c],p=c,c<<=1);h[map[ind[p]=ind[n]]=p]=h[n];n--;return 1;}};elem_t prim(int n,edge_t* list[],int* pre){heap h;elem_t min[MAXN],ret=0,e;edge_t* t;int v[MAXN],i;for (h.init(),i=0;i<n;i++)min[i]=(i?inf:0),v[i]=0,pre[i]=-1,h.ins(i,min[i]);while (h.delmin(i,e))for (v[i]=1,ret+=e,t=list[i];t;t=t->next)if (!v[t->to]&&t->len<min[t->to])pre[t->to]=t->from,h.del(t->to,e),h.ins(t->to,min[t->to]=t->le n);return ret;}6. 最小生成树(prim+mapped_heap正向表形式)//无向图最小生成树,prim算法+映射二分堆,正向表形式,复杂度O(mlogn)//返回最小生成树的长度,传入图的大小n和正向表list,buf//可更改边权的类型,pre[]返回树的构造,用父结点表示,根节点(第一个)pre值为-1 //必须保证图的连通的!#define MAXN 200#define inf 1000000000typedef double elem_t;struct edge_t{int to;elem_t len;};#define _cp(a,b) ((a)<(b))struct heap{elem_t h[MAXN+1];int ind[MAXN+1],map[MAXN+1],n,p,c;void init(){n=0;}void ins(int i,elem_t e){for(p=++n;p>1&&_cp(e,h[p>>1]);h[map[ind[p]=ind[p>>1]]=p]=h[p>>1],p>> =1);h[map[ind[p]=i]=p]=e;}int del(int i,elem_t& e){i=map[i];if (i<1||i>n) return 0;for(e=h[p=i];p>1;h[map[ind[p]=ind[p>>1]]=p]=h[p>>1],p>>=1);for(c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[map[ind[p]= ind[c]]=p]=h[c],p=c,c<<=1);h[map[ind[p]=ind[n]]=p]=h[n];n--;return 1;}int delmin(int& i,elem_t& e){if (n<1) return 0;i=ind[1];for(e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[ma p[ind[p]=ind[c]]=p]=h[c],p=c,c<<=1);h[map[ind[p]=ind[n]]=p]=h[n];n--;return 1;}};elem_t prim(int n,int* list,edge_t* buf,int* pre){heap h;elem_t min[MAXN],ret=0,e;int v[MAXN],i,j;for (h.init(),i=0;i<n;i++)min[i]=(i?inf:0),v[i]=0,pre[i]=-1,h.ins(i,min[i]);while (h.delmin(i,e))for (v[i]=1,ret+=e,j=list[i];j<list[i+1];j++)if (!v[buf[j].to]&&buf[j].len<min[buf[j].to])pre[buf[j].to]=i,h.del(buf[j].to,e),h.ins(buf[j].to,min[buf[j] .to]=buf[j].len);return ret;}7. 最小生成树(prim邻接阵形式)//无向图最小生成树,prim算法,邻接阵形式,复杂度O(n^2)//返回最小生成树的长度,传入图的大小n和邻接阵mat,不相邻点边权inf//可更改边权的类型,pre[]返回树的构造,用父结点表示,根节点(第一个)pre值为-1 //必须保证图的连通的!#define MAXN 200#define inf 1000000000typedef double elem_t;elem_t prim(int n,elem_t mat[][MAXN],int* pre){elem_t min[MAXN],ret=0;int v[MAXN],i,j,k;for (i=0;i<n;i++)min[i]=inf,v[i]=0,pre[i]=-1;for (min[j=0]=0;j<n;j++){for (k=-1,i=0;i<n;i++)if (!v[i]&&(k==-1||min[i]<min[k]))k=i;for (v[k]=1,ret+=min[k],i=0;i<n;i++)if (!v[i]&&mat[k][i]<min[i])min[i]=mat[pre[i]=k][i];}return ret;}8. 最小树形图(邻接阵形式)//多源最小树形图,edmonds算法,邻接阵形式,复杂度O(n^3)//返回最小生成树的长度,构造失败返回负值//传入图的大小n和邻接阵mat,不相邻点边权inf//可更改边权的类型,pre[]返回树的构造,用父结点表示//传入时pre[]数组清零,用-1标出源点#include <string.h>#define MAXN 120#define inf 1000000000typedef int elem_t;elem_t edmonds(int n,elem_t mat[][MAXN*2],int* pre){elem_t ret=0;int c[MAXN*2][MAXN*2],l[MAXN*2],p[MAXN*2],m=n,t,i,j,k;for (i=0;i<n;l[i]=i,i++);do{memset(c,0,sizeof(c)),memset(p,0xff,sizeof(p));for (t=m,i=0;i<m;c[i][i]=1,i++);for (i=0;i<t;i++)if (l[i]==i&&pre[i]!=-1){for (j=0;j<m;j++)if(l[j]==j&&i!=j&&mat[j][i]<inf&&(p[i]==-1||mat[j][i]<mat[p[i]][i]) )p[i]=j;if ((pre[i]=p[i])==-1)return -1;if (c[i][p[i]]){for (j=0;j<=m;mat[j][m]=mat[m][j]=inf,j++);for (k=i;l[k]!=m;l[k]=m,k=p[k])for (j=0;j<m;j++)if (l[j]==j){if (mat[j][k]-mat[p[k]][k]<mat[j][m])mat[j][m]=mat[j][k]-mat[p[k]][k];if (mat[k][j]<mat[m][j])mat[m][j]=mat[k][j];}c[m][m]=1,l[m]=m,m++;}for (j=0;j<m;j++)if (c[i][j])for (k=p[i];k!=-1&&l[k]==k;c[k][j]=1,k=p[k]);}}while (t<m);for (;m-->n;pre[k]=pre[m])for (i=0;i<m;i++)if (l[i]==m){for (j=0;j<m;j++)if (pre[j]==m&&mat[i][j]==mat[m][j])pre[j]=i;if (mat[pre[m]][m]==mat[pre[m]][i]-mat[pre[i]][i])k=i;}for (i=0;i<n;i++)if (pre[i]!=-1)ret+=mat[pre[i]][i];return ret;}四.图论_网络流1. 上下界最大流(邻接表形式)//求上下界网络最大流,邻接表形式//返回最大流量,-1表示无可行流,flow返回每条边的流量//传入网络节点数n,容量mat,流量下界bf,源点source,汇点sink//MAXN应比最大结点数多2,无可行流返回-1时mat未复原!#define MAXN 100#define inf 1000000000int _max_flow(int n,int mat[][MAXN],int source,int sink,int flow[][MAXN]){int pre[MAXN],que[MAXN],d[MAXN],p,q,t,i,j,r;vector<int> e[MAXN];for (i=0;i<n;i++)for (e[i].clear(),j=0;j<n;j++)if (mat[i][j]) e[i].push_back(j),e[j].push_back(i);for (;;){for (i=0;i<n;pre[i++]=0);pre[t=source]=source+1,d[t]=inf;for (p=q=0;p<=q&&!pre[sink];t=que[p++])for (r=0;r<e[t].size();++r){i=e[t][r];if (!pre[i]&&(j=mat[t][i]-flow[t][i]))pre[que[q++]=i]=t+1,d[i]=d[t]<j?d[t]:j;else if (!pre[i]&&(j=flow[i][t]))pre[que[q++]=i]=-t-1,d[i]=d[t]<j?d[t]:j;}if (!pre[sink]) break;for (i=sink;i!=source;)if (pre[i]>0)flow[pre[i]-1][i]+=d[sink],i=pre[i]-1;elseflow[i][-pre[i]-1]-=d[sink],i=-pre[i]-1;}for (j=i=0;i<n;j+=flow[source][i++]);return j;。
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算法模板(吉林大学)
目录目录 (1)Graph 图论 (3)|DAG的深度优先搜索标记 (3)|无向图找桥 (3)|无向图连通度(割) (3)|最大团问题DP+DFS (3)|欧拉路径O(E) (3)|D IJKSTRA数组实现O(N^2) (3)|D IJKSTRA O(E* LOG E) (4)|B ELLMAN F ORD单源最短路O(VE) (4)|SPFA(S HORTEST P ATH F ASTER A LGORITHM) (4)|第K短路(D IJKSTRA) (5)|第K短路(A*) (5)|P RIM求MST (6)|次小生成树O(V^2) (6)|最小生成森林问题(K颗树)O(MLOGM) (6)|有向图最小树形图 (6)|M INIMAL S TEINER T REE (6)|T ARJAN强连通分量 (7)|弦图判断 (7)|弦图的PERFECT ELIMINATION点排列 (7)|稳定婚姻问题O(N^2) (7)|拓扑排序 (8)|无向图连通分支(DFS/BFS邻接阵) (8)|有向图强连通分支(DFS/BFS邻接阵)O(N^2) (8)|有向图最小点基(邻接阵)O(N^2) (9)|F LOYD求最小环 (9)|2-SAT问题 (9)Network 网络流 (11)|二分图匹配(匈牙利算法DFS实现) (11)|二分图匹配(匈牙利算法BFS实现) (11)|二分图匹配(H OPCROFT-C ARP的算法) (11)|二分图最佳匹配(KUHN MUNKRAS算法O(M*M*N))..11 |无向图最小割O(N^3) (12)|有上下界的最小(最大)流 (12)|D INIC最大流O(V^2*E) (12)|HLPP最大流O(V^3) (13)|最小费用流O(V*E* F).......................................13|最小费用流O(V^2* F). (14)|最佳边割集 (15)|最佳点割集 (15)|最小边割集 (15)|最小点割集(点连通度) (16)|最小路径覆盖O(N^3) (16)|最小点集覆盖 (16)Structure 数据结构 (17)|求某天是星期几 (17)|左偏树合并复杂度O(LOG N) (17)|树状数组 (17)|二维树状数组 (17)|T RIE树(K叉) (17)|T RIE树(左儿子又兄弟) (18)|后缀数组O(N* LOG N) (18)|后缀数组O(N) (18)|RMQ离线算法O(N*LOG N)+O(1) (19)|RMQ(R ANGE M INIMUM/M AXIMUM Q UERY)-ST算法(O(NLOGN +Q)) (19)|RMQ离线算法O(N*LOG N)+O(1)求解LCA (19)|LCA离线算法O(E)+O(1) (20)|带权值的并查集 (20)|快速排序 (20)|2台机器工作调度 (20)|比较高效的大数 (20)|普通的大数运算 (21)|最长公共递增子序列O(N^2) (22)|0-1分数规划 (22)|最长有序子序列(递增/递减/非递增/非递减) (22)|最长公共子序列 (23)|最少找硬币问题(贪心策略-深搜实现) (23)|棋盘分割 (23)|汉诺塔 (23)|STL中的PRIORITY_QUEUE (24)|堆栈 (24)|区间最大频率 (24)|取第K个元素 (25)|归并排序求逆序数 (25)|逆序数推排列数 (25)|二分查找 (25)|二分查找(大于等于V的第一个值) (25)|所有数位相加 (25)Number 数论 (26)|递推求欧拉函数PHI(I) (26)|单独求欧拉函数PHI(X) (26)|GCD最大公约数 (26)|快速GCD (26)|扩展GCD (26)|模线性方程 A * X = B (% N) (26)|模线性方程组 (26)|筛素数[1..N] (26)|高效求小范围素数[1..N] (26)|随机素数测试(伪素数原理) (26)|组合数学相关 (26)|P OLYA计数 (27)|组合数C(N, R) (27)|最大1矩阵 (27)|约瑟夫环问题(数学方法) (27)|约瑟夫环问题(数组模拟) (27)|取石子游戏1 (27)|集合划分问题 (27)|大数平方根(字符串数组表示) (28)|大数取模的二进制方法 (28)|线性方程组A[][]X[]=B[] (28)|追赶法解周期性方程 (28)|阶乘最后非零位,复杂度O(NLOGN) (29)递归方法求解排列组合问题 (30)|类循环排列 (30)|全排列 (30)|不重复排列 (30)|全组合 (31)|不重复组合 (31)|应用 (31)模式串匹配问题总结 (32)|字符串H ASH (32)|KMP匹配算法O(M+N) (32)|K ARP-R ABIN字符串匹配 (32)|基于K ARP-R ABIN的字符块匹配 (32)|函数名: STRSTR (32)|BM算法的改进的算法S UNDAY A LGORITHM (32)|最短公共祖先(两个长字符串) (33)|最短公共祖先(多个短字符串)...............................33Geometry 计算几何.. (34)|G RAHAM求凸包O(N* LOG N) (34)|判断线段相交 (34)|求多边形重心 (34)|三角形几个重要的点 (34)|平面最近点对O(N* LOG N) (34)|L IUCTIC的计算几何库 (35)|求平面上两点之间的距离 (35)|(P1-P0)*(P2-P0)的叉积 (35)|确定两条线段是否相交 (35)|判断点P是否在线段L上 (35)|判断两个点是否相等 (35)|线段相交判断函数 (35)|判断点Q是否在多边形内 (35)|计算多边形的面积 (35)|解二次方程A X^2+B X+C=0 (36)|计算直线的一般式A X+B Y+C=0 (36)|点到直线距离 (36)|直线与圆的交点,已知直线与圆相交 (36)|点是否在射线的正向 (36)|射线与圆的第一个交点 (36)|求点P1关于直线LN的对称点P2 (36)|两直线夹角(弧度) (36)ACM/ICPC竞赛之STL (37)ACM/ICPC竞赛之STL简介 (37)ACM/ICPC竞赛之STL--PAIR (37)ACM/ICPC竞赛之STL--VECTOR (37)ACM/ICPC竞赛之STL--ITERATOR简介 (38)ACM/ICPC竞赛之STL--STRING (38)ACM/ICPC竞赛之STL--STACK/QUEUE (38)ACM/ICPC竞赛之STL--MAP (40)ACM/ICPC竞赛之STL--ALGORITHM (40)STL IN ACM (41)头文件 (42)线段树 (43)求矩形并的面积(线段树+离散化+扫描线) (43)求矩形并的周长(线段树+离散化+扫描线) (44)Graph 图论/*==================================================*\| DAG的深度优先搜索标记| INIT: edge[][]邻接矩阵; pre[], post[], tag全置0;| CALL: dfstag(i, n); pre/post:开始/结束时间\*==================================================*/int edge[V][V], pre[V], post[V], tag;void dfstag(int cur, int n){ // vertex: 0 ~ n-1pre[cur] = ++tag;for (int i=0; i<n; ++i) if (edge[cur][i]) {if (0 == pre[i]) {printf("Tree Edge!\n");dfstag(i,n);} else {if (0 == post[i]) printf("Back Edge!\n");else if (pre[i] > pre[cur])printf("Down Edge!\n");else printf("Cross Edge!\n");}}post[cur] = ++tag;}/*==================================================*\| 无向图找桥| INIT: edge[][]邻接矩阵;vis[],pre[],anc[],bridge 置0;| CALL: dfs(0, -1, 1, n);\*==================================================*/int bridge, edge[V][V], anc[V], pre[V], vis[V];void dfs(int cur, int father, int dep, int n){ // vertex: 0 ~ n-1if (bridge) return;vis[cur] = 1; pre[cur] = anc[cur] = dep;for (int i=0; i<n; ++i) if (edge[cur][i]) {if (i != father && 1 == vis[i]) {if (pre[i] < anc[cur])anc[cur] = pre[i];//back edge}if (0 == vis[i]) { //tree edgedfs(i,cur,dep+1,n);if (bridge) return;if (anc[i] < anc[cur]) anc[cur] = anc[i];if (anc[i] > pre[cur]) { bridge = 1; return; } }}vis[cur] = 2;}/*==================================================*\| 无向图连通度(割)| INIT: edge[][]邻接矩阵;vis[],pre[],anc[],deg[]置为0;| CALL: dfs(0, -1, 1, n);| k=deg[0], deg[i]+1(i=1…n-1)为删除该节点后得到的连通图个数| 注意:0作为根比较特殊!\*==================================================*/int edge[V][V], anc[V], pre[V], vis[V], deg[V];void dfs(int cur, int father, int dep, int n){// vertex: 0 ~ n-1int cnt = 0;vis[cur] = 1; pre[cur] = anc[cur] = dep;for (int i=0; i<n; ++i) if (edge[cur][i]) {if (i != father && 1 == vis[i]) {if (pre[i] < anc[cur])anc[cur] = pre[i];//back edge}if (0 == vis[i]) { //tree edgedfs(i,cur,dep+1,n);++cnt; // 分支个数if (anc[i] < anc[cur]) anc[cur] = anc[i];if ((cur==0 && cnt>1) ||(cnt!=0 && anc[i]>=pre[cur]))++deg[cur];// link degree of a vertex }}vis[cur] = 2;} /*==================================================*\| 最大团问题 DP + DFS| INIT: g[][]邻接矩阵;| CALL: res = clique(n);\*==================================================*/int g[V][V], dp[V], stk[V][V], mx;int dfs(int n, int ns, int dep){if (0 == ns) {if (dep > mx) mx = dep;return 1;}int i, j, k, p, cnt;for (i = 0; i < ns; i++) {k = stk[dep][i]; cnt = 0;if (dep + n - k <= mx) return 0;if (dep + dp[k] <= mx) return 0;for (j = i + 1; j < ns; j++) {p=stk[dep][j];if (g[k][p]) stk[dep + 1][cnt++] = p;}dfs(n, cnt, dep + 1);}return 1;}int clique(int n){int i, j, ns;for (mx = 0, i = n - 1; i >= 0; i--) {// vertex: 0 ~ n-1for (ns = 0, j = i + 1; j < n; j++)if (g[i][j]) stk[1][ ns++ ] = j;dfs(n, ns, 1); dp[i] = mx;}return mx;}/*==================================================*\| 欧拉路径O(E)| INIT: adj[][]置为图的邻接表; cnt[a]为a点的邻接点个数;| CALL: elpath(0); 注意:不要有自向边\*==================================================*/int adj[V][V], idx[V][V], cnt[V], stk[V], top;int path(int v){for (int w ; cnt[v] > 0; v = w) {stk[ top++ ] = v;w = adj[v][ --cnt[v] ];adj[w][ idx[w][v] ] = adj[w][ --cnt[w] ];// 处理的是无向图—-边是双向的,删除v->w后,还要处理删除w->v}return v;}void elpath (int b, int n){ // begin from b int i, j;for (i = 0; i < n; ++i) // vertex: 0 ~ n-1 for (j = 0; j < cnt[i]; ++j)idx[i][ adj[i][j] ] = j;printf("%d", b);for (top = 0; path(b) == b && top != 0; ) {b = stk[ --top ];printf("-%d", b);}printf("\n");}/*==================================================*\| Dijkstra数组实现O(N^2)| Dijkstra --- 数组实现(在此基础上可直接改为STL的Queue实现)| lowcost[] --- beg到其他点的最近距离| path[] -- beg为根展开的树,记录父亲结点\*==================================================*/#define INF 0x03F3F3F3Fconst int N;int path[N], vis[N];void Dijkstra(int cost[][N], int lowcost[N], int n, int beg){ int i, j, min;memset(vis, 0, sizeof(vis));vis[beg] = 1;for (i=0; i<n; i++){lowcost[i] = cost[beg][i]; path[i] = beg;}lowcost[beg] = 0;path[beg] = -1; // 树根的标记int pre = beg;for (i=1; i<n; i++){min = INF;dist[v] = dist[u] + c;for (j=0; j<n; j++)// 下面的加法可能导致溢出,INF 不能取太大if (vis[j]==0 &&lowcost[pre]+cost[pre][j]<lowcost[j]){lowcost[j] =lowcost[pre] + cost[pre][j]; path[j] = pre; } for (j=0; j<n; j++) if (vis[j] == 0 && lowcost[j] < min){ min = lowcost[j]; pre = j; } vis[pre] = 1; } } /*==================================================*\ | Dijkstra O(E * log E) | INIT: 调用init(nv, ne)读入边并初始化; | CALL: dijkstra(n, src); dist[i]为src 到i 的最短距离 \*==================================================*/ #define typec int // type of cost const typec inf = 0x3f3f3f3f; // max of cost typec cost[E], dist[V]; int e, pnt[E], nxt[E], head[V], prev[V], vis[V]; struct qnode { int v; typec c; qnode (int vv = 0, typec cc = 0) : v(vv), c(cc) {} bool operator < (const qnode& r) const { return c>r.c; } }; void dijkstra(int n, const int src){ qnode mv; int i, j, k, pre; priority_queue<qnode> que; vis[src] = 1; dist[src] = 0; que.push(qnode(src, 0)); for (pre = src, i=1; i<n; i++) { for (j = head[pre]; j != -1; j = nxt[j]) { k = pnt[j]; if (vis[k] == 0 && dist[pre] + cost[j] < dist[k]){ dist[k] =dist[pre] + cost[j]; que.push(qnode(pnt[j], dist[k])); prev[k] = pre; } } while (!que.empty() && vis[que.top().v] == 1) que.pop(); if (que.empty()) break ; mv = que.top(); que.pop(); vis[pre = mv.v] = 1; } } inline void addedge(int u, int v, typec c){ pnt[e] = v; cost[e] = c; nxt[e] = head[u]; head[u] = e++; } void init(int nv, int ne){ int i, u, v; typec c; e = 0;memset(head, -1, sizeof (head));memset(vis, 0, sizeof (vis));memset(prev, -1, sizeof (prev));for (i = 0; i < nv; i++) dist[i] = inf;for (i = 0; i < ne; ++i) {scanf("%d%d%d", &u, &v, &c);// %d: type of cost addedge(u, v, c); // vertex: 0 ~ n-1, 单向边 }}/*==================================================*\| BellmanFord 单源最短路O(VE)| 能在一般情况下,包括存在负权边的情况下,解决单源最短路径问题| INIT: edge[E][3]为边表| CALL: bellman(src);有负环返回0;dist[i]为src 到i 的最短距| 可以解决差分约束系统: 需要首先构造约束图,构造不等式时>=表示求最小值, 作为最长路,<=表示求最大值, 作为最短路 (v-u <= c:a[u][v] = c )\*==================================================*/#define typec int // type of costconst typec inf=0x3f3f3f3f; // max of costint n, m, pre[V], edge[E][3];typec dist[V];int relax (int u, int v, typec c){if (dist[v] > dist[u] + c) {pre[v] = u; return 1; } return 0; } int bellman (int src){ int i, j;for (i=0; i<n; ++i) { dist[i] = inf; pre[i] = -1; } dist[src] = 0; bool flag; for (i=1; i<n; ++i){ flag = false; // 优化 for (j=0; j<m; ++j) { if( 1 == relax(edge[j][0], edge[j][1], edge[j][2]) ) flag = true; } if( !flag ) break; } for (j=0; j<m; ++j) { if (1 == relax(edge[j][0], edge[j][1], edge[j][2])) return 0; // 有负圈 } return 1; } /*==================================================*\ | SPFA(Shortest Path Faster Algorithm) Bellman-Ford 算法的一种队列实现,减少了不必要的冗余计算。
ACM算法总结
(1)几何公式.
(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)
(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)
(poj1408,poj1584)
(4)最小树形图(poj3164)
(5)次小生成树.
(6)无向图、有向图的最小环
三.数据结构.
(1)trie图的建立和应用. (poj2778)
(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和 在线算法
(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)
(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)
五.动态规划
(1)背包问题. (poj1837,poj1276)
(2)型如下表的简单DP(可参考lrj的书 page149):
(4)凸包. (poj2187,poj1113)
中级:
一.基本算法:
(1)C++的标准模版库的应用. (poj3096,poj3007)
(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)
二.图算法:
(3)记忆化搜索(poj3373,poj1691)
五.动态规划
(1)较为复杂的动态规划(如动态规划解特别的施行商问题等)
(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)
(2)四边形不等式理论.
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_算法模板集史上最完整收藏版223页全免费版(1)
免费模板~~~ACM Standard Code LibraryHuang WeiSoftware EngineeringComputer and Software CollegeHangzhou Dianzi UniversityOctober,2008ACM算法模板集Contents一.常用函数与STL二.重要公式与定理1.Fibonacci Number2.Lucas Number3.Catalan Number4.Stirling Number(Second Kind)5.Bell Number6.Stirling's Approximation7.Sum of Reciprocal Approximation8.Young Tableau9.整数划分10.错排公式11.三角形内切圆半径公式12.三角形外接圆半径公式13.圆內接四边形面积公式14.基础数论公式三.大数模板,字符读入四.数论算法1.Greatest Common Divisor最大公约数2.Prime素数判断3.Sieve Prime素数筛法4.Module Inverse模逆元5.Extended Euclid扩展欧几里德算法6.Modular Linear Equation模线性方程(同余方程)7.Chinese Remainder Theorem中国余数定理(互素与非互素)8.Euler Function欧拉函数9.Farey总数9.Farey序列构造ler_Rabbin素数测试,Pollard_rho因式分解五.图论算法1.最小生成树(Kruscal算法)2.最小生成树(Prim算法)3.单源最短路径(Bellman-ford算法)4.单源最短路径(Dijkstra算法)5.全源最短路径(Folyd算法)6.拓扑排序7.网络预流和最大流8.网络最小费用最大流9.网络最大流(高度标号预流推进)10.最大团11.最大匹配(Hungary,HopcroftKarp算法)12.带权二分图最优匹配(KM算法)13.强连通分量(Kosaraju算法)14.强连通分量(Gabow算法)15.无向图割边割点和双连通分量16.最小树形图O(N^3)17.最小树形图O(VE)六.几何算法1.几何模板2.球面上两点最短距离3.三点求圆心坐标4.三角形几个重要的点七.专题讨论1.树状数组2.字典树3.后缀树4.线段树5.并查集6.二叉堆7.逆序数(归并排序)8.树状DP9.欧拉路10.八数码11.高斯消元法12.字符串匹配(KMP算法)13.全排列,全组合14.二维线段树15.稳定婚姻匹配16.后缀数组17.左偏树18.标准RMQ-ST19.度限制最小生成树20.最优比率生成树(0/1分数规划)21.最小花费置换22.区间K大数23.LCA-RMQ-ST24.LCA–Tarjan25.指数型母函数26.指数型母函数(大数据)27.AC自动机(字典树+KMP)28.FFT(大数乘法)29.二分图网络最大流最小割30.混合图欧拉回路31.无源汇上下界网络流32.二分图最小点权覆盖33.带约束的轨道计数(Burnside引理)34.三分法求函数波峰35.单词计数,DFA自动机,Trie图(完全AC自动机)36.字符串和数值hash37.滚动队列,前向星表示法38.最小点基,最小权点基39.LCSubsequence O(N^2/logN)40.伸展树41.Treap42.0/1分数规划K约束43.表达式求值44.乘除法博弈,Wythoff博弈45.状态压缩的积木型DP46.解一般线性方程组(消元法)47.块状链表48.Factor Oracle第一章常用函数和STL一.常用函数#include<stdio.h>int getchar(void);//读取一个字符,一般用来去掉无用字符char*gets(char*str);//读取一行字符串#include<stdlib.h>void*malloc(size_t size);//动态内存分配,开辟大小为size的空间void qsort(void*buf,size_t num,size_t size,int(*compare)(const void*,const void*));//快速排序Sample:int compare_ints(const void*a,const void*b){int*arg1=(int*)a;int*arg2=(int*)b;if(*arg1<*arg2)return-1;else if(*arg1==*arg2)return0;else return1;}int array[]={-2,99,0,-743,2,3,4};int array_size=7;qsort(array,array_size,sizeof(int),compare_ints);#include<math.h>//求反正弦,arg∈[-1,1],返回值∈[-pi/2,+pi/2]double asin(double arg);//求正弦,arg为弧度,弧度=角度*Pi/180.0,返回值∈[-1,1]double sin(double arg);//求e的arg次方double exp(double arg);//求num的对数,基数为edouble log(double num);//求num的根double sqrt(double num);//求base的exp次方double pow(double base,double exp);#include<string.h>//初始化内存,常用来初始化数组void*memset(void*buffer,int ch,size_t count);memset(the_array,0,sizeof(the_array));//printf是它的变形,常用来将数据格式化为字符串int sprintf(char*buffer,const char*format,...);sprintf(s,"%d%d",123,4567);//s="1234567"//scanf是它的变形,常用来从字符串中提取数据int sscanf(const char*buffer,const char*format,...);Sample:char result[100]="24hello",str[100];int num;sprintf(result,"%d%s",num,str);//num=24;str="hello";//字符串比较,返回值<0代表str1<str2,=0代表str1=str2,>0代表str1>str2 int strcmp(const char*str1,const char*str2);二.常用STL[标准container概要]vector<T>大小可变的向量,类似数组的用法,容易实现删除list<T>双向链表queue<T>队列,empty(),front(),pop(),push()stack<T>栈,empty(),top(),pop(),push()priority_queue<T>优先队列,empty(),top(),pop(),push()set<T>集合map<key,val>关联数组,常用来作hash映射[标准algorithm摘录]for_each()对每一个元素都唤起(调用)一个函数find()查找第一个能与引数匹配的元素replace()用新的值替换元素,O(N)copy()复制(拷贝)元素,O(N)remove()移除元素reverse()倒置元素sort()排序,O(N log(N))partial_sort()部分排序binary_search()二分查找merge()合并有序的序列,O(N)[C++String摘录]copy()从别的字符串拷贝empty()判断字符串是否为空erase()从字符串移除元素find()查找元素insert()插入元素length()字符串长度replace()替换元素substr()取子字符串swap()交换字符串第二章重要公式与定理1.Fibonacci Number0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610…Formula:011211i i i n n F F F F F F −−===+⎡⎤⎥==⎥⎠⎦2.Lucas Number1,3,4,7,11,18,29,47,76,123...Formula:n nn L =+⎝⎠⎝⎠3.Catalan Number1,2,5,14,42,132,429,1430,4862,16796,58786,208012…Formula:110(2,)1*n n n i n ii C n n Cat n Cat Cat Cat −−−==+=∑Application:1)将n +2边形沿弦切割成n 个三角形的不同切割数Sample:n =2;n =3;2)n +1个数相乘,给每两个元素加上括号的不同方法数Sample:n =2;(1(23)),((12)3)n =3;(1(2(34))),(1((23)4)),((12)(34)),((1(23))4),(((12)3)4)3)n 个节点的不同形状的二叉树数(严《数据结构》P .155)4)从n *n 方格的左上角移动到右下角不升路径数Sample:n =2;n =3;4.Stirling Number(Second Kind)S(n,m)表示含n 个元素的集合划分为m 个集合的情况数或者是n 个有标号的球放到m 个无标号的盒子中,要求无一为空,其不同的方案数Formula:,1,11,0 (0 || ) (1)n m n m n m m n m S S m S n m −−−=<⎧⎨+×>≥⎩,01(1)(,)()!m i n n m i S C m i m i m ==−××−∑Special Cases:,0,11,2,3,1,01211(3323)6(,2)1n n n n n n n n n n n S S S S S C n S −−===−=−×+==5.Bell Numbern 个元素集合所有的划分数Formula:,0nn n ii B S ==∑6.Stirling's Approximation!nn n e ⎞=⎟⎠7.Sum of Reciprocal ApproximationEulerGamma =0.57721566490153286060651209;11ln() ()n i n EulerGamma n i==+→∞∑8.Young TableauYoung Tableau(杨式图表)是一个矩阵,它满足条件:如果格子[i,j]没有元素,则[i+1,j]也一定没有元素如果格子[i,j]有元素a[i,j],则[i+1,j]要么没有元素,要么a[i+1,j]>a[i,j]Y[n]代表n 个数所组成的杨式图表的个数Formula:121212(1) (2)n n n Y Y Y Y n Y n −−===+−×>Sample:n =3;9.整数划分将整数n 分成k 份,且每份不能为空,任意两种分法不能相同1)不考虑顺序for (int p=1;p<=n ;p++)for (int i=p;i<=n ;i++)for (int j=k;j>=1;j--)dp[i][j]+=dp[i-p][j-1];cout<<dp[n][k]<<endl;2)考虑顺序dp[i][j]=dp[i-k][j-1];(k=1..i)3)若分解出来的每个数均有一个上限mdp[i][j]=dp[i-k][j-1];(k=1..m)10.错排公式121201(1)()n n n D D D n D D −−===−×+11.三角形内切圆半径公式22a b cp s sr a b c++===++12.三角形外接圆半径公式4abcR s=13.圆內接四边形面积公式2a b c dp s +++==14.基础数论公式1)模取幂%((((%)*)%))%n a b a b a b b=…2)n 的约数的个数若n 满足1212m n n n m n p p p =+++…,则n 的约数的个数为12(1)(1)(1)m n n n +++…第三章大数模板typedef int hugeint;//应不大于,以防乘法时溢出const int Base=1000;const int Capacity=1000;struct xnum{int Len;int Data[Capacity];xnum():Len(0){}xnum(const xnum&V):Len(V.Len){memcpy(Data,V.Data,Len*sizeof*Data);}xnum(int V):Len(0){for(;V>0;V/=Base)Data[Len++]=V%Base;}xnum(char S[]);xnum&operator=(const xnum&V){Len=V.Len;memcpy(Data,V.Data,Len*sizeof*Data);return*this;}int&operator[](int Index){return Data[Index];}int operator[](int Index)const{return Data[Index];}void print(){printf("%d",Len==0?0:Data[Len-1]);for(int i=Len-2;i>=0;i--)for(int j=Base/10;j>0;j/=10)printf("%d",Data[i]/j%10);}};xnum::xnum(char S[]){int I,J;Data[Len=0]=0;J=1;for(I=strlen(S)-1;I>=0;I--){Data[Len]+=(S[I]-'0')*J;J*=10;if(J>=Base)J=1,Data[++Len]=0;}if(Data[Len]>0)Len++;}int compare(const xnum&A,const xnum&B){int I;if(A.Len!=B.Len)return A.Len>B.Len?1:-1;for(I=A.Len-1;I>=0&&A[I]==B[I];I--);if(I<0)return0;return A[I]>B[I]?1:-1;}xnum operator+(const xnum&A,const xnum&B){xnum R;int I;int Carry=0;for(I=0;I<A.Len||I<B.Len||Carry>0;I++) {if(I<A.Len)Carry+=A[I];if(I<B.Len)Carry+=B[I];R[I]=Carry%Base;Carry/=Base;}R.Len=I;return R;}xnum operator-(const xnum&A,const xnum&B){xnum R;int Carry=0;R.Len=A.Len;int I;for(I=0;I<R.Len;I++){R[I]=A[I]-Carry;if(I<B.Len)R[I]-=B[I];if(R[I]<0)Carry=1,R[I]+=Base;else Carry=0;}while(R.Len>0&&R[R.Len-1]==0)R.Len--;return R;}xnum operator*(const xnum&A,const int B){int I;if(B==0)return0;xnum R;hugeint Carry=0;for(I=0;I<A.Len||Carry>0;I++){if(I<A.Len)Carry+=hugeint(A[I])*B;R[I]=Carry%Base;Carry/=Base;}R.Len=I;return R;}xnum operator*(const xnum&A,const xnum&B){int I;if(B.Len==0)return0;xnum R;for(I=0;I<A.Len;I++){hugeint Carry=0;for(int J=0;J<B.Len||Carry>0;J++){if(J<B.Len)Carry+=hugeint(A[I])*B[J];if(I+J<R.Len)Carry+=R[I+J];if(I+J>=R.Len)R[R.Len++]=Carry%Base;else R[I+J]=Carry%Base;Carry/=Base;}}return R;}xnum operator/(const xnum&A,const int B){xnum R;int I;hugeint C=0;for(I=A.Len-1;I>=0;I--){C=C*Base+A[I];R[I]=C/B;C%=B;}R.Len=A.Len;while(R.Len>0&&R[R.Len-1]==0)R.Len--;return R;}//divxnum operator/(const xnum&A,const xnum&B){int I;xnum R,Carry=0;int Left,Right,Mid;for(I=A.Len-1;I>=0;I--){Carry=Carry*Base+A[I];Left=0;Right=Base-1;while(Left<Right){Mid=(Left+Right+1)/2;if(compare(B*Mid,Carry)<=0)Left=Mid;else Right=Mid-1;}R[I]=Left;Carry=Carry-B*Left;}R.Len=A.Len;while(R.Len>0&&R[R.Len-1]==0)R.Len--;return R;}//modxnum operator%(const xnum&A,const xnum&B){int I;xnum R,Carry=0;int Left,Right,Mid;for(I=A.Len-1;I>=0;I--){Carry=Carry*Base+A[I];Left=0;Right=Base-1;while(Left<Right){Mid=(Left+Right+1)/2;if(compare(B*Mid,Carry)<=0)Left=Mid;else Right=Mid-1;}R[I]=Left;Carry=Carry-B*Left;}R.Len=A.Len;while(R.Len>0&&R[R.Len-1]==0)R.Len--;return Carry;}istream&operator>>(istream&In,xnum&V){char Ch;for(V=0;In>>Ch;){V=V*10+(Ch-'0');if(cin.peek()<='')break;}return In;}ostream&operator<<(ostream&Out,const xnum&V){int I;Out<<(V.Len==0?0:V[V.Len-1]);for(I=V.Len-2;I>=0;I--)for(int J=Base/10;J>0;J/=10)Out<<V[I]/J%10;return Out;}xnum gcd(xnum a,xnum b){if(compare(b,0)==0)return a;else return gcd(b,a%b);}int div(char*A,int B){int I;int C=0;int Alen=strlen(A);for(I=0;I<Alen;I++){C=C*Base+A[I]-'0';C%=B;}return C;}xnum C(int n,int m){int i;xnum sum=1;for(i=n;i>=n-m+1;i--)sum=sum*i;for(i=1;i<=m;i++)sum=sum/i;return sum;}#define MAXN9999#define DLEN4class BigNum{private:int a[1000];//可以控制大数的位数int len;//大数长度public:BigNum(){len=1;memset(a,0,sizeof(a));} BigNum(const int);BigNum(const char*);BigNum(const BigNum&);BigNum&operator=(const BigNum&);BigNum operator+(const BigNum&)const;BigNum operator-(const BigNum&)const;BigNum operator*(const BigNum&)const;BigNum operator/(const int&)const;BigNum operator^(const int&)const;int operator%(const int&)const;bool operator>(const BigNum&T)const;void print();};BigNum::BigNum(const int b){int c,d=b;len=0;memset(a,0,sizeof(a));while(d>MAXN){c=d-(d/(MAXN+1))*(MAXN+1);d=d/(MAXN+1);a[len++]=c;}a[len++]=d;}BigNum::BigNum(const char*s){int t,k,index,l,i;memset(a,0,sizeof(a));l=strlen(s);len=l/DLEN;if(l%DLEN)len++;index=0;for(i=l-1;i>=0;i-=DLEN){t=0;k=i-DLEN+1;if(k<0)k=0;for(int j=k;j<=i;j++)t=t*10+s[j]-'0';a[index++]=t;}}BigNum::BigNum(const BigNum&T):len(T.len){ int i;memset(a,0,sizeof(a));for(i=0;i<len;i++)a[i]=T.a[i];}BigNum&BigNum::operator=(const BigNum&n){ len=n.len;memset(a,0,sizeof(a));int i;for(i=0;i<len;i++)a[i]=n.a[i];return*this;}BigNum BigNum::operator+(const BigNum&T)const{ BigNum t(*this);int i,big;//位数big=T.len>len?T.len:len;for(i=0;i<big;i++){t.a[i]+=T.a[i];if(t.a[i]>MAXN){t.a[i+1]++;t.a[i]-=MAXN+1;}}if(t.a[big]!=0)t.len=big+1;else t.len=big;return t;}BigNum BigNum::operator-(const BigNum&T)const{ int i,j,big;bool flag;BigNum t1,t2;if(*this>T){t1=*this;t2=T;flag=0;}else{t1=T;t2=*this;flag=1;}big=t1.len;for(i=0;i<big;i++){if(t1.a[i]<t2.a[i]){j=i+1;while(t1.a[j]==0)j++;t1.a[j--]--;while(j>i)t1.a[j--]+=MAXN;t1.a[i]+=MAXN+1-t2.a[i];}else t1.a[i]-=t2.a[i];}t1.len=big;while(t1.a[len-1]==0&&t1.len>1){t1.len--;big--;}if(flag)t1.a[big-1]=0-t1.a[big-1];return t1;}BigNum BigNum::operator*(const BigNum&T)const{BigNum ret;int i,j,up;int temp,temp1;for(i=0;i<len;i++){up=0;for(j=0;j<T.len;j++){temp=a[i]*T.a[j]+ret.a[i+j]+up;if(temp>MAXN){temp1=temp-temp/(MAXN+1)*(MAXN+1);up=temp/(MAXN+1);ret.a[i+j]=temp1;}else{up=0;ret.a[i+j]=temp;}}if(up!=0)ret.a[i+j]=up;}ret.len=i+j;while(ret.a[ret.len-1]==0&&ret.len>1)ret.len--;return ret;}BigNum BigNum::operator/(const int&b)const{BigNum ret;int i,down=0;for(i=len-1;i>=0;i--){ret.a[i]=(a[i]+down*(MAXN+1))/b;down=a[i]+down*(MAXN+1)-ret.a[i]*b;}ret.len=len;while(ret.a[ret.len-1]==0&&ret.len>1)ret.len--;return ret;}int BigNum::operator%(const int&b)const{int i,d=0;for(i=len-1;i>=0;i--){d=((d*(MAXN+1))%b+a[i])%b;}return d;}BigNum BigNum::operator^(const int&n)const{BigNum t,ret(1);if(n<0)exit(-1);if(n==0)return1;if(n==1)return*this;int m=n;while(m>1){t=*this;int i;for(i=1;i<<1<=m;i<<=1){t=t*t;}m-=i;ret=ret*t;if(m==1)ret=ret*(*this);}return ret;}bool BigNum::operator>(const BigNum&T)const{ int ln;if(len>T.len)return true;else if(len==T.len){ln=len-1;while(a[ln]==T.a[ln]&&ln>=0)ln--;if(ln>=0&&a[ln]>T.a[ln])return true;else return false;}else return false;}void BigNum::print(){int i;cout<<a[len-1];for(i=len-2;i>=0;i--){cout.width(DLEN);cout.fill('0');cout<<a[i];}}//读取整数const int ok=1;int get_val(int&ret){ret=0;char ch;while((ch=getchar())>'9'||ch<'0');do{ret=ret*10+ch-'0';}while((ch=getchar())<='9'&&ch>='0');return ok;}//带负数int get_val(int&ret){ret=0;char ch;bool neg=false;while(((ch=getchar())>'9'||ch<'0')&&ch!='-');if(ch=='-'){neg=true;while((ch=getchar())>'9'||ch<'0');}do{ret=ret*10+ch-'0';}while((ch=getchar())<='9'&&ch>='0');ret=(neg?-ret:ret);return ok;}//读取整数,可判EOF和EOLconst int eof=-1;const int eol=-2;int get_val(int&ret){ret=0;char ch;while(((ch=getchar())>'9'||ch<'0')&&ch!=EOF);if(ch==EOF)return eof;do{ret=ret*10+ch-'0';}while((ch=getchar())<='9'&&ch>='0');if(ch=='\n')return eol;return ok;}//读取浮点数int get_val(double&ret){ret=0;double base=0.1;char ch;bool dot=false,neg=false;while(((ch=getchar())>'9'||ch<'0')&&ch!='.'&&ch!='-');if(ch=='-'){neg=true;while(((ch=getchar())>'9'||ch<'0')&&ch!='.'&&ch!='-');}do{if(ch=='.'){dot=true;continue;}if(dot){ret+=(ch-'0')*base;base*=0.1;}else ret=ret*10+(ch-'0');}while(((ch=getchar())<='9'&&ch>='0')||ch=='.');ret=(neg?-ret:ret);return ok;}typedef long long LL;//LL MultiMod(LL a,LL b,LL c){//if(b)//return(a*(b&1)%c+(MultiMod(a,b>>1,c)<<1))%c; //return0;//}LL MultiMod(LL a,LL b,LL c){LL ret=0,d=a;for(;b;b>>=1,d<<=1,d%=c)if((b&1))ret=(ret+d)%c;return ret;}//128-bits integer's power with mod in O(64*LogN)LL ModPower(LL base,LL exp,LL mod){LL ret=1;for(;exp;exp>>=1,base=MultiMod(base,base,mod)) if((exp&1))ret=MultiMod(ret,base,mod);return ret;}第四章数论算法1.Greatest Common Divisor最大公约数int GCD(int x,int y){int t;while(y>0){t=x%y;x=y;y=t;}return x;}2.Prime素数判断bool is_prime(int u){if(u==0||u==1)return false;if(u==2)return true;if(u%2==0)return false;for(int i=3;i<=sqrt(u);i+=2)if(u%i==0)return false;return true;}3.Sieve Prime素数筛法const int M=1000;//M:sizebool mark[M];//true:prime numbervoid sieve_prime(){memset(mark,true,sizeof(mark));mark[0]=mark[1]=false;for(int i=2;i<=sqrt(M);i++){if(mark[i]){for(int j=i*i;j<M;j+=i)mark[j]=false;}}}4.Module Inverse模逆元//ax≡1(mod n)int Inv(int a,int n){int d,x,y;d=extended_euclid(a,n,x,y);if(d==1)return(x%n+n)%n;else return-1;//no solution}5.Extended Euclid扩展欧几里德算法//如果GCD(a,b)=d,则存在x,y,使d=ax+by//extended_euclid(a,b)=ax+byint extended_euclid(int a,int b,int&x,int&y){int d;if(b==0){x=1;y=0;return a;}d=extended_euclid(b,a%b,y,x);y-=a/b*x;return d;}6.Modular Linear Equation模线性方程(同余方程) //如果GCD(a,b)不能整除c,则ax+by=c没有整数解//ax≡b(mod n)n>0//上式等价于二元一次方程ax–ny=bvoid modular_linear_equation(int a,int b,int n){int d,x,y,x0,gcd;//可以减少扩展欧几里德溢出的可能gcd=GCD(a,n);if(b%gcd!=0){cout<<"no solution"<<endl;return;}a/=gcd;b/=gcd;n/=gcd;d=extended_euclid(a,n,x,y);if(b%d==0){x0=(x*(b/d))%n;//x0:basic solutionint ans=n;//min x=(x0%(n/d)+(n/d))%(n/d)for(int i=0;i<d;i++){ans=(x0+i*(n/d))%n;cout<<ans<<endl;}}else cout<<"no solution"<<endl;}7.Chinese Remainder Theorem中国余数定理//x≡b[i](mod w[i]),i∈[1,len-1]//前提条件w[i]>0,且w[]中任意两个数互质int chinese_remainder(int b[],int w[],int len){int i,d,x,y,m,n,ret;ret=0;n=1;for(i=0;i<len;i++)n*=w[i];for(i=0;i<len;i++){m=n/w[i];d=extended_euclid(w[i],m,x,y);ret=(ret+y*m*b[i])%n;}return(n+ret%n)%n;}//m≡r[i](mod a[i])//a[i]可以不互素//-1表示无解/*Pku2891Strange Way to Express Integers假设C≡A1(mod B1),C≡A2(mod B2)。
16个ACM经典算法介绍
所以在 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超级经典算法大集合
超级经典算法大集合:老掉牙河内塔费式数列巴斯卡三角形三色棋老鼠走迷官(一)老鼠走迷官(二)骑士走棋盘八个皇后八枚银币生命游戏字串核对双色、三色河内塔背包问题(KnapsackProblem)数、运算蒙地卡罗法求PI Eratosthenes筛选求质数超长整数运算(大数运算)长PI最大公因数、最小公倍数、因式分解完美数阿姆斯壮数最大访客数中序式转后序式(前序式)后序式的运算关于赌博洗扑克牌(乱数排列)Craps赌博游戏约瑟夫问题(JosephusProblem)集合问题排列组合格雷码(GrayCode)产生可能的集合m元素集合的n个元素子集数字拆解排序得分排行选择、插入、气泡排序Shell 排序法- 改良的插入排序Shaker 排序法-改良的气泡排序Heap 排序法- 改良的选择排序快速排序法(一)快速排序法(二)快速排序法(三)合并排序法基数排序法搜寻循序搜寻法(使用卫兵)二分搜寻法(搜寻原则的代表)插补搜寻法费氏搜寻法矩阵稀疏矩阵多维矩阵转一维矩阵上三角、下三角、对称矩阵奇数魔方阵4N 魔方阵2(2N+1) 魔方阵1.河内之塔说明河内之塔(Towers of Hanoi)是法国人M.Claus(Lucas)于1883年从泰国带至法国的,河内为越战时北越的首都,即现在的胡志明市;1883年法国数学家Edouard Lucas曾提及这个故事,据说创世纪时Benares有一座波罗教塔,是由三支钻石棒(Pag)所支撑,开始时神在第一根棒上放置64个由上至下依由小至大排列的金盘(Disc),并命令僧侣将所有的金盘从第一根石棒移至第三根石棒,且搬运过程中遵守大盘子在小盘子之下的原则,若每日仅搬一个盘子,则当盘子全数搬运完毕之时,此塔将毁损,而也就是世界末日来临之时。
解法如果柱子标为ABC,要由A搬至C,在只有一个盘子时,就将它直接搬至C,当有两个盘子,就将B当作辅助柱。
如果盘数超过2个,将第三个以下的盘子遮起来,就很简单了,每次处理两个盘子,也就是:A->B、A ->C、B->C这三个步骤,而被遮住的部份,其实就是进入程式的递回处理。
acm算法经典例题
acm算法经典例题一、数论1: Wolf and Rabbit描述There is a hill with n holes around. The holes are signed from0 to n-1.A rabbit must hide in one of the holes. A wolf searches the rabbit in anticlockwise order. The first hole he get into is the one signed with 0. Then he will get into the hole every m holes. For example, m=2 and n=6, the wolf will get into the holes which are signed 0,2,4,0. If the rabbit hides in the hole which signed 1,3 or 5, she will survive. So we call these holes the safe holes.输入The input starts with a positive integer P which indicates the number of test cases. Then on the following P lines,each line consists 2 positive integer m and n(0<m,n<2147483648).< bdsfid="69" p=""></m,n<2147483648).<>输出For each input m n, if safe holes exist, you should output "YES", else output "NO" in a single line.样例输入21 22 2样例输出NOYES翻译:描述一座山有n个洞,洞被标记为从0到n-1。
ACM算法全集
1--1:零和区间#include <stdio.h>#include<string.h>#include<math.h>#include<iostream>using namespace std;int min=1000000;int max=-1;void contrast(int d){if(d<min)min=d;if(d>max)max=d;}void main(){int n;int d;scanf("%d",&n);int abssum;int max1=-1;int *a=NULL;a=(int *)malloc((n+1)*sizeof(int));int *b=NULL;b=(int *)malloc((n+1)*sizeof(int));memset(b,0,(n+1)*sizeof(int));int sum=0;for(int i=1;i<=n;i++){scanf("%d",&a[i]);b[i]=b[i-1]+a[i];abssum=abs(b[i]);if(abssum>max1)max1=abssum;}int *l=NULL;int *r=NULL;l=(int*)malloc((2*max1+1)*sizeof(int));r=(int*)malloc((2*max1+1)*sizeof(int));memset(l,-1,(2*max1+1)*sizeof(int) );memset(r,-1,(2*max1+1)*sizeof(int) );l[max1]=0;for(i=1;i<=n;i++){b[i]=b[i]+max1;if(l[b[i]]==-1){l[b[i]]=i;}else if(r[b[i]]==-1){r[b[i]]=i;d=r[b[i]]-l[b[i]];contrast(d);}else{d=i-r[b[i]];contrast(d);r[b[i]]=i;d=r[b[i]]-l[b[i]];contrast(d);}}if(max==-1)printf("-1\n");else{printf("%d\n",min);printf("%d\n",max);}}1--2亲兄弟问题#include<stdio.h>#include<malloc.h>#include<cstdio>#include<iostream>using namespace std;struct mystack{int top;int len;int *val;}st;void InitStack(int n){st.val=(int *)malloc(sizeof(int)*n);st.top=-1;st.len=n;}int main(){int n;int i;while(~scanf("%d",&n)){InitStack(n);int*ans=(int*)malloc(n*sizeof(int));int *a=(int *)malloc(n*sizeof(int));for(i=0;i<n;++i)scanf("%d",a+i);i=0;st.val[++st.top]=i++;while(i<n&&st.top<st.len&&st.top> =0){if(a[i]<a[st.val[st.top]])st.val[++st.top]=i;else{while(st.top>=0&&a[i]>=a[st.val[st. top]])ans[st.val[st.top--]]=i;st.val[++st.top]=i;}i++;}while(st.top>=0)ans[st.val[st.top--]]=-1;for(i=0;i<n-1;i++)printf("%d ",ans[i]);printf("%d\n",ans[i]);free(st.val);free(a);free(ans);}return 0;}1--3最大覆盖问题#include <stdio.h>#include<limits.h>#include<math.h>#include<algorithm>#include<string.h>int cover(int a[],int n){int i,j;int res=1;int right=-1;for(j=i=n-1;j>=0;j--){if(abs(a[j])>right){while(abs(a[j])>=a[i-1])i--;res=res>j-i?res:j-i;right=abs(a[j]);}}return res;}int main(){int n;scanf("%d",&n);int *a;a=(int *)malloc(sizeof(int)*n);for(int i=0;i<n;i++)scanf("%d",&a[i]);printf("%d\n",cover(a,n));return 0;}1--4高精度整数问题#include<stdio.h>int a[20000]={0};int Prime(int *p, int n){int i,j,count=0;for(i=2; i<=n; i++){if(a[i]==0){p[count++]=i;for(j=2;i*j<=n;j++){a[i*j]=1;}}}return count;}int Power(int n, int p) {int sum=0;while(n){sum+=n/p;n/=p;}return sum;}int Mult(int *a, int p, int k){int i;int c=0;for(i=0;i<k;i++){a[i]=a[i]*p+c;c=a[i]/10000;a[i]%=10000;}while(c){a[k++]=c%10000;c/=10000;} return k;}void Output(int *num, int*prime, int k){ int re[2000]={1},sz=1;int i, j;for(i=0;i<k;i++){for(j=0;j<num[i];j++){sz=Mult(re, prime[i], sz);}}printf("%d",re[sz-1]);for(i=sz-2;i>=0;i--){printf("%.4d",re[i]);}printf("\n");}int main(){intprime[2000],num1[2000],num2[2000];int k, n, m, i;scanf("%d %d", &m, &n);k=Prime(prime,2*m);for(i=0;i<k;i++){int t1 = Power(m,prime[i]);int t2 = Power(n,prime[i]);int t3 = Power(m-n,prime[i]);int t4 = Power(2*m,prime[i]);int t5 = Power(m+1, prime[i]);num1[i]=t1-t2-t3;num2[i]=t4-t1-t5;}Output(num1, prime, k);Output(num2, prime, k);return 0;}1--5最大间隙问题#include<stdio.h>#include<iostream>using namespace std;int main(){int i,n;while(scanf("%d",&n)!=EOF){double *a=new double[n];for( i=0;i<n;i++)scanf("%lf",&a[i]);double max,min;max=min=a[0];for(i=1;i<n;i++){if(a[i]<min)min=a[i];if(a[i]>max)max=a[i];}doubleintervallength=(max-min)/(n-1);int *flag=new int[n];double *smallest=new double[n];double *largest=new double[n];for(i=0;i<n;i++){flag[i]=0;smallest[i]=max;largest[i]=min;}int interval=0;for(i=0;i<n;i++){interval=(int)((a[i]-min)/intervallength);flag[interval]++;if(a[i]<smallest[interval])smallest[interval]=a[i];if(a[i]>largest[interval])largest[interval]=a[i];}double tmp, progmax=0;double bp=largest[0];for(i=1;i<n;i++){if(flag[i]!=0){tmp=smallest[i]-bp;if(tmp>progmax)progmax=tmp;bp=largest[i];}}cout<<progmax<<endl;delete[] a;delete[] flag;delete[] smallest;delete[] largest;}return 0; }2—1合式公式#include <stdio.h>#include <stdlib.h>#include <string>#define N 200char zifu[N];int pos;int flag;int state[5];int get(){switch(zifu[pos++]){case 'p':return state[0];case 'q':return state[1];case 'r':return state[2];case 's':return state[3];case 't':return state[4];case 'K':return get()&get();case 'A':return get()|get();case 'N':return !get();case 'C':return !get()|get();case 'E':return get()==get();}}void main(){// gets(zifu);while(scanf("%s",zifu)!=EOF) {if(zifu[0]=='0')break;flag=1;for(state[0]=0;state[0]<=1&&flag;st ate[0]++){for(state[1]=0;state[1]<=1&&flag;st ate[1]++){for(state[2]=0;state[2]<=1&&flag;st ate[2]++){for(state[3]=0;state[3]<=1&&flag;st ate[3]++){for(state[4]=0;state[4]<=1&&flag;st ate[4]++){pos=0;if(get()==0){flag=0; break;}}}}}}if(flag==1)printf("1\n");elseprintf("0\n");//gets(zifu);}}2—2期盼分割#include <stdio.h>#include <math.h> #include <string.h>#define inf 99999999#define min(a,b) (a<b?a:b)int s[9][9];int f[16][9][9][9][9];int n;//int inf=99999999;double ave;void init(){int i,j,temp,v;memset(s,0,sizeof(s));memset(f,-1,sizeof(f));for(i=1;i<=8;i++){for(j=1,temp=0;j<=8;j++){scanf("%d",&v);temp+=v;s[i][j]=temp;if(i>1) s[i][j]+=s[i-1][j];}}ave=((double)s[8][8])*1.0/n;}int get_sum(int x1,int y1,int x2,int y2) {int ans=0;ans+=s[x2][y2];if(x1>1) ans-=s[x1-1][y2];if(y1>1) ans-=s[x2][y1-1];if(x1>1&&y1>1)ans+=s[x1-1][y1-1];return ans*ans;}int dfs(int k,int x1,int y1,int x2,int y2) {int i,j,w1,w2,temp;if(f[k][x1][y1][x2][y2]!=-1) return f[k][x1][y1][x2][y2];if(k==1) {f[k][x1][y1][x2][y2]=get_sum(x1,y1,x2,y2);return f[k][x1][y1][x2][y2];}int ans=inf;for(i=x1;i<x2;i++)//水平分割{w1=dfs(k-1,x1,y1,i,y2)+get_sum(i+ 1,y1,x2,y2);w2=dfs(k-1,i+1,y1,x2,y2)+get_sum( x1,y1,i,y2);temp=min(w1,w2);ans=min(ans,temp);}for(j=y1;j<y2;j++)//竖直分割{w1=dfs(k-1,x1,y1,x2,j)+get_sum(x1 ,j+1,x2,y2);w2=dfs(k-1,x1,j+1,x2,y2)+get_sum( x1,y1,x2,j);temp=min(w1,w2);ans=min(ans,temp);}f[k][x1][y1][x2][y2]=ans;return ans;}void main(){while(scanf("%d",&n)!=EOF){if(n==0) break;init();int ans=dfs(n,1,1,8,8);doubleres=((double)ans)*1.0/n-ave*ave;//printf("%.3lf",sqrt(ret/n*1.0-ave*a ve));printf("%.3lf\n",sqrt(res));}}2—3放苹果#include<stdio.h>int apple(int m,int n){if(m==0||n==1)return 1;else if(m<0)return 0;elsereturnapple(m-n,n)+apple(m,n-1);}void main(){int t;scanf("%d",&t);while(t--){int m;int n;scanf("%d",&m);scanf("%d",&n);printf("%d\n",apple(m,n));}}2—4 树上路径问题#include <iostream>#define INFINITY 0x7ffffffusing namespace std;typedef struct{int *vexs;int **arcs;int vexnum,arcnum;}Graph;typedef struct {int start;int end;int deep;}pset;class Stack{public:Stack(){base=(int*)malloc(3000*sizeof(int));start=end=0;}Stack(int n){base=(int*)malloc(n*sizeof(int));start=end=0;}StackInit(){start=end=0;}public:int *base;int start;int end;};//全局数组bool *visited; //访问标志数组int psetcount;pset *p;void CreateUDN(Graph &G, int vexnum){int i,j,w,s1,s2;//cin>>G.vexnum>>k;G.vexnum=vexnum;G.arcnum=G.vexnum-1;G.vexs=(int*)malloc(G.vexnum*sizeof(int));G.arcs=(int**)malloc(G.vexnum*sizeof(int));for(i=0;i<G.vexnum;i++)G.arcs[i]=(int*)malloc(G.vexnum*sizeof(int));for(i=0;i<G.vexnum;i++)G.vexs[i]=i;for(i=0;i<G.vexnum;i++)for(j=0;j<G.vexnum;j++)G.arcs[i][j]=INFINITY;for(i=0;i<G.arcnum;i++){cin>>s1>>s2>>w;G.arcs[s1][s2]=G.arcs[s2][s1]=w;}}int FirstVex(Graph G,int k){if(k>=0 && k<G.vexnum){for(int i=0;i<G.vexnum;i++)if(G.arcs[k][i]!=INFINITY) return i;}return -1;}int NextVex(Graph G,int i,int j){if(i>=0 && i<G.vexnum && j>=0 && j<G.vexnum){ //i,j合理for(int k=j+1;k<G.vexnum;k++)if(G.arcs[i][k]!=INFINITY) return k;}return -1;}//深度优先遍历void DFS(Graph G,int k,int weight,Stack &q){int i,weighttmp=0;if(weight<0){visited[k]=true;q.end--;return;}else if(weight==0){visited[k]=true;//q.base[q.end++]=k;p[psetcount].end=k;p[psetcount].start=q.base[0];p[psetcount].deep=q.end-1;//cout<<"path :"<<psetcount<<endl;//for(i=0;i<q.end;i++)// cout<<q.base[i]<<" ";//cout<<endl;psetcount++;q.end--;return;}/*if(k==-1){ //第一次执行DFS时,k 为-1for(i=0;i<G.vexnum;i++)if(!visited[i]){q.base[q.end++]=i;DFS(G,i,weight,q); //对尚未访问的顶点调用DFS}} *///else{visited[k]=true;for(i=FirstVex(G,k);i>=0;i=NextVex (G,k,i))if(!visited[i]){q.base[q.end++]=i;DFS(G,i,weight-G.arcs[k][i],q); //对k的尚未访问的邻接顶点i递归调用DFS}q.end--;//} }//主函数int main(){int i,j,vexnum,weight,temp;Graph G;cin>>vexnum>>weight;CreateUDN(G,vexnum);visited=(bool*)malloc(G.vexnum*sizeof(bool));Stack s(vexnum);p=(pset*)malloc(G.vexnum*G.vexnum*sizeof(p set));//mset(p,0,G.vexnum*sizeof(pset));for(i=0;i<G.vexnum*G.vexnum;i++) p[i].deep=INFINITY;psetcount=0;for(j=0;j<G.vexnum;j++){for(i=0;i<G.vexnum;i++)visited[i]=false;s.StackInit();s.base[s.end++]=j;//使第一个点进栈DFS(G,j,weight,s);}temp=p[0].deep;for(i=0;i<G.vexnum;i++)if(temp>p[i].deep)temp=p[i].deep;if(temp==INFINITY)cout<<-1;elsecout<<temp;free(G.vexs);for(i=0;i<G.vexnum;i++)free(G.arcs[i]);free(G.arcs);return 0;}2—5 最近点对问题#include <iostream>#include <algorithm>#include <math.h>#define N 100000using namespace std;struct node{double x;double y;}node1[100000];struct node a[100000];double min(double x,double y){return x<y?x:y;}int compx(struct node node1,struct node node2){return node1.x<node2.x;}int compy(struct node node1,struct node node2){return node1.y<node2.y;}double dis(struct node node3,struct node node4){returnsqrt((node3.x-node4.x)*(node3.x-node4. x)+(node3.y-node4.y)*(node3.y-node4.y ));}double getmindis(int left,int right) {int cnt=0;int i,j;//double d1;//double d2;if(left==right) return 0;if(left+1==right) return dis(node1[left],node1[right]);if(left+2==right) return min(min(dis(node1[left],node1[left+1]), dis(node1[left+1],node1[right])),dis(nod e1[left],node1[right]));int mid=(left+right)/2;//d1=getmindis(left,mid);//d2=getmindis(mid+1,right);doubled=min(getmindis(left,mid),getmindis(mi d+1,right));for(i=left;i<=right;i++)if(node1[i].x>node1[mid].x-d&&node1[ i].x<node1[mid].x+d)a[cnt++]=node1[i];sort(a,a+cnt,compy);for( i=0;i<cnt;i++){for(j=i+1;j<cnt;j++){if(a[j].y-a[i].y>=d)break;d=min(d,dis(a[i],a[j]));}}return d;}void main(){int n;int i;double distance;while(scanf("%d",&n)!=EOF&&n){for(i=0;i<n;i++){scanf("%lf",&node1[i].x);scanf("%lf",&node1[i].y);}sort(node1,node1+n,compx);distance=getmindis(0,n-1);printf("%.2lf\n",distance/2);}}3—1石子划分#include <stdio.h>#include <algorithm>#define size 1000using namespace std;int list[size];int f[size][size];void fun(int n,int m){int min;int i;int temp;i=n;i--;min=f[n-1][m-1];for(i;i>1;i--){temp=f[i-1][m-1]+(list[n]-list[i])*(li st[n]-list[i]);if(min>temp) min=temp;}f[n][m]=min;}void main(){int n;int m;int i;int j;scanf("%d",&n);scanf("%d",&m);for(i=1;i<=n;i++)scanf("%d",&list[i]);sort(list+1,list+n+1);f[1][1]=0;for(i=2;i<=n;i++)f[i][1]=(list[i]-list[1])*(list[i]-list[1]) ;for(j=2;j<=m;j++){for(i=2;i<=n;i++){fun(i,j);}}printf("%d\n",f[n][m]);}3--2 逆序数问题#include <stdio.h>#define Mod 10000int dp[1003][1003];int main(){int n,k,i,j;scanf("%d %d",&n,&k);for(i = 1;i <= n; i ++){dp[i][0] = 1;}for(i = 2; i <= n; i ++){for(j = 1; j <= (i * (i - 1) / 2) && j <= k ;j ++){if(j < i){dp[i][j] = (dp[i][j - 1] + dp[i - 1][j])%Mod;}if(j >= i){dp[i][j] = (dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - i] + Mod) % Mod;}}}printf("%d\n",dp[n][k]);return 0;}3—3 石子合并问题#include<iostream>#include <limits.h>using namespace std;int f[101][101];int w[101][101];int num[101];int res[101];void main(){int i,j,k,t,temp;int n;int mmin;scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d",&num[i]);memset(w,0,sizeof(w));memset(f,0,sizeof(f));for(t=0;t<n;t++){if(t!=0){temp=num[t];num[t]=num[t+1];num[t+1]=temp;}for(i=1;i<=n;i++)w[i][i]=num[i];for(i=1;i<=n-1;i++)for(j=i+1;j<=n;j++)w[i][j]=w[i][j-1]+num[j];for(i=n;i>=1;i--){for(j=i+1;j<=n;j++){mmin=INT_MAX;for(k=i;k<j;k++){if(f[i][k]+f[k+1][j]<mmin)mmin=f[i][k]+f[k+1][j];}f[i][j]=mmin+w[i][j];}}res[t]=f[1][n];if(t!=0){temp=num[t];num[t]=num[t+1];num[t+1]=temp;}}int min = INT_MAX;int swi;for(i=0;i<n;i++){if(res[i]<=min){min=res[i];swi=i;}}if(res[0]==min)swi=0;printf("%d\n",min);printf("(%d,%d)\n",swi,swi+1); }3—4 上升序列问题#include <stdio.h>#include <math.h>#define size 10000+1void main(){int m;int n;int j;int temp;int max=1;int l;int x;int a[size]={0};int b[size]={0};int dp[size];for(int i=1;i<size;i++)dp[i]=1;scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&a[i]);//scanf("%d",&b[n-i+1]);b[n-i+1]=a[i];}for(i=2;i<=n;i++){int max1=0;for(j=1;j<i;j++){if(b[j]>b[i]&&dp[j]>max1){max1=dp[j];dp[i]=max1+1;}}if(dp[i]>max)max=dp[i];}for(i=1;i<=n/2;i++){temp=dp[i];dp[i]=dp[n-i+1];dp[n-i+1]=temp;}scanf("%d",&m);while(m--){scanf("%d",&l);if(l>max){printf("Impossible\n");continue;}for(i=1;i<=n&&l>dp[i];i++){} // j=i++;//i--;printf("%d ",a[i]);l--;x=a[i];j=i++;for(j;j<=n&&l;j++){if(dp[j]>=l&&a[j]>x){printf("%d ",a[j]);x=a[j];l--;}}printf("\n");}}3—5服务器转移问题#include<iostream>using namespace std;int main(){int n,i,j,k;scanf("%d",&n);int * dist = new int[n];int * weight = new int[n];int * weight2 = new int[n];_int64 * cost = new _int64[n];_int64 * cost2 = new _int64[n];_int64 min = -1;_int64 temp;for(i=0;i<n;i++){scanf("%d %d",&weight[n-i-1],&di st[n-i-1]);weight2[n-i-1]=weight[n-i-1];}for(i=n-2;i>=0;i--){weight2[i]+=weight2[i+1];}cost[0]=weight2[0]*dist[0];for(i=1;i<n;i++){cost[i]=cost[i-1]+weight2[i]*dist[i];}for(i=1;i<n;i++){dist[i]+=dist[i-1];}cost2[0]=weight[0]*dist[0];for(i=1;i<n;i++){cost2[i]=cost2[i-1]+weight[i]*dist[i] ;}for(i=0;i<n-1;i++){for (j=i+1;j<n;j++){temp=cost[n-1]-cost[j];if(i>0)temp+=cost2[i-1];//printf("%d %d %I64d\n",i+1,j+1,t emp);for(k=i+1;k<j;k++){temp+=weight[k]*(dist[k]-dist[i]);}if(min==-1){min=temp;}else if (min>temp){min=temp;//printf("%d %d\n",i,j);}}}printf("%I64d\n",min);return 0;}4—1任务分配问题#include<iostream>#include<queue> #include<stdlib.h>#include<algorithm>#include <functional>using namespace std;struct node{int start;int end;}node1[10001];int cmp(struct node a,struct node b) {if(a.start!=b.start)return a.start<b.start;elsereturn a.end<b.end;}void main(){int n;priority_queue<int,vector<int>,grea ter<int> > q;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d%d",&node1[i].start,&no de1[i].end);}sort(node1,node1+n,cmp);for(i=0;i<n;i++){if(q.size()==0){q.push(node1[i].end);continue;}if(node1[i].start>q.top()){q.pop();}q.push(node1[i].end);}printf("%d\n",q.size());}4—2 木材加工问题#include <stdio.h>#include <math.h>#include<algorithm>#include<string.h>using namespace std;struct node{int l;int w;}node1[5001];int cmp(struct node a,struct node b) {if(a.l!=b.l)return a.l<b.l;return a.w<b.w;}int greedy(struct node node2[],int n) {int k=0;int j=0;struct node *node3=NULL;node3=(struct node *)malloc(n*sizeof(struct node));for(int i=1;i<n;i++){if(node2[i].w>=node2[j].w){j=i;}else{node3[k++]=node2[i];}}if(k==0)return 1;else if(k==1)return 2;elsereturn 1+greedy(node3,k); }void main(){int count;int n;scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d%d",&node1[i].l,&node1[i].w );sort(node1,node1+n,cmp);count=greedy(node1,n);printf("%d\n",count);}4—3 旅行时间问题#include <stdio.h>#include <math.h>//#define min 0xffffffvoid main(){int n;int temp;float v;int t;int min=0xffffff;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%f%d",&v,&t);if(t<0)continue;else{temp=ceil(4.5*3600/v)+t;if(temp<min)min=temp;}}printf("%d\n",min);}4—4 整数接力问题#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct node{char zifu[11];}a[100001];int cmp(struct node b,struct node c) {char temp1[22];char temp2[22];strcpy(temp1,b.zifu);strcat(temp1,c.zifu);strcpy(temp2,c.zifu);strcat(temp2,b.zifu);return strcmp(temp1,temp2)>0; }void main(){int n;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%s",a[i].zifu);}sort(a,a+n,cmp);for(i=0;i<n;i++)printf("%s",a[i].zifu);printf("\n");}4—5雷达设置问题#include <stdio.h>#include <math.h>#include<algorithm>#define size 1000using namespace std;struct node{double l;double r;}node1[size];int cmp(struct node a,struct node b) {if(a.l!=b.l)return a.l<b.l;return a.r<b.r;}void main(){int n;int d;int x;int y;int cnt;double temp;while(scanf("%d%d",&n,&d)!=EOF ){cnt=1;for(int i=0;i<n;i++){scanf("%d",&x);scanf("%d",&y);if(y>d){cnt=-1;}else{temp=sqrt(d*d-y*y);node1[i].l=x-temp;node1[i].r=x+temp;}}if(cnt==-1){printf("%d\n",-1);continue;}sort(node1,node1+n,cmp);temp=node1[0].r;for(i=1;i<n;i++){if(node1[i].l>temp){cnt++;temp=node1[i].r;}else{if(node1[i].r<temp)temp=node1[i].r;}}printf("%d\n",cnt);}}5—1 棋盘上的象#include <iostream>#include <cmath>#include<cstdio>using namespace std;#define N 7int b[N*N+1];int n,k;__int64 sum;bool test(int t){int i;for(i=1;i<t;++i)if(abs(b[i]/n-b[t]/n)==abs(b[i]%n-b[t]%n ))return false;return true;}void fun(int t){if(t>k){sum++;return;}int i;for(i=b[t-1]+1;i<=n*n;++i){b[t]=i;if(test(t))fun(t+1);}}int main(){while(~scanf("%d%d",&n,&k)){if(k>2*n-2)printf("0\n");else{sum=0;b[0]=0;fun(1);printf("%I64d\n",sum);}}return 0;}5—2 表达式游戏#include <stdio.h>#include <iostream>#include <string.h>#include <math.h>#define size 12using namespace std;_int64 best=-1;int n;int k;_int64 current;int a[size]={0};int isornotk(_int64 i){while(i){if(i%10!=k)i=i/10;else return 1;}return 0;}void backtrack(int i){if(i==n){if(isornotk(current)==0){if(current>best){best=current;return;}}}else{for(int j=1;j<=4;j++){_int64 temp=current;switch(j){case 1:if(current==0||a[i+1]==0)continue;current=current+a[i+1];backtrack(i+1);current=temp;break;case 2:if(current>a[i+1])current=current-a[i+1];elsecurrent=a[i+1]-current;backtrack(i+1);current=temp;break;case 3:if((current==0 && a[i+1]==0)||(current==2 && a[i+1]==2))continue;current=current*a[i+1];backtrack(i+1);current=temp;break;case 4:if(a[i+1]==0) continue;current=current/a[i+1];backtrack(i+1);current=temp;break;}}}}void main(){scanf("%d",&n);scanf("%d",&k);for(int i=1;i<=n;i++)scanf("%d",&a[i]);current=a[1];backtrack(1);if(best==-1)printf("No result\n");elseprintf("%I64d\n",best);}5—3队伍#include <stdio.h>#include <string.h>#define size 10#include<time.h>clock_t start,finish;int jisuan(int *p,int n,int l,int r){int *f=p;if(n==1&&l==1&&r==1) return 1;else if(n==0||l==0||r==0) return 0;else{returnjisuan(f,n-1,l,r)*(n-2)+jisuan(f,n-1,l-1,r) +jisuan(f,n-1,l,r-1);}}void main(){int f[size][size][size]={0,0};f[1][1][1]=1;int n;int l;int r;int *p;p=(int*)f;scanf("%d%d%d",&n,&l,&r);//start=clock();int count=jisuan(p,n,l,r);printf("%d",count);printf("\n");//finish=clock();//printf("%d",finish-start);}5—4拔河#include <iostream>#include <cmath>using namespace std;int a[24];int ans,newans,sum,n,counta;void dfs(int t){if(counta==(n>>1)){if (ans>abs(sum-2*newans)) ans=abs(sum-2*newans);return ;}if (t>=n) return;newans+=a[t];counta++;dfs(t+1);counta--;newans-=a[t];dfs(t+1);}int main(){int i;scanf("%d",&n);sum=0;ans=0x7FFFFFFF;for(i=0;i<n;i++){scanf("%d",&a[i]);sum+=a[i];}newans=0;counta=0;dfs(0);printf("%d %d\n",(sum-ans)>>1,(sum+ans)>> 1);return 0; }5—5 覆盖问题#include <stdio.h>#include <string.h>#define size 22int n;int xi[size]={0};int yi[size]={0};int ci[size]={0};int flag[size]={0};int min=900000;int current=0;int r;void backtrack(int i){if(i>n){int flag1=1;for(int j=1;j<=n;j++){if(flag[j]==0){flag1=0;break;}}if(current<min&&flag1==1)min=current;return;}if(current+ci[i]<min){current=current+ci[i];for(int j=1;j<=n;j++){if(r*r>=(xi[i]-xi[j])*(xi[i]-xi[j])+(yi[ i]-yi[j])*(yi[i]-yi[j]))flag[j]++;}backtrack(i+1);current=current-ci[i];for( j=1;j<=n;j++){if(r*r>=(xi[i]-xi[j])*(xi[i]-xi[j])+(yi[ i]-yi[j])*(yi[i]-yi[j]))flag[j]--;}}backtrack(i+1);}void main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&xi[i]);scanf("%d",&yi[i]);scanf("%d",&ci[i]);}scanf("%d",&r);backtrack(1);printf("%d\n",min);}6—1 色子游戏问题#include <iostream>#include <queue>using namespace std;int m;int n;typedef struct{int x;int y;int up;int down;int front;int back;int left;int right;int step;}state;state start; state end;bool used[101][101][7][7];bool grid[101][101];bool check(state first){if(first.x<0||first.x>=m||first.y<0||firs t.y>=n)return false;else return grid[first.x][first.y];}state go(state first,int i){state ans=first;//int temp;switch(i){case 0:ans.x--;ans.down=first.front;ans.front=first.up;ans.up=first.back;ans.back=first.down;ans.left=first.left;ans.right=first.right;//return ans;break;case 1:ans.x++;ans.front=first.down;ans.back=first.up;ans.left=first.left;ans.right=first.right;ans.up=first.front;ans.down=first.back;//return ans;break;case 2:ans.y--;ans.front=first.front;ans.back=first.back;ans.left=first.up;ans.right=first.down;ans.up=first.right;ans.down=first.left;//return ans;。
ACM常用算法
ACM常用算法1)递推求解:首先,确认:能否容易的得到简单情况的解;然后,假设:规模为N-1的情况已经得到解决;最后,重点分析:当规模扩大到N时,如何枚举出所有的情况,并且要确保对于每一种子情况都能用已经得到的数据解决。
例题1在一个平面上有一个圆和n条直线,这些直线中每一条在圆内同其他直线相交,假设没有3条直线相交于一点,试问这些直线将圆分成多少区域。
分析F(1)=2;F(n) = F(n-1)+n;化简后为F(n) = n(n+1)/2 +1;例题2 平面上有n条折线,问这些折线最多能将平面分割成多少块?分析把折线当作两天直线相交然后再减去交集延伸部分。
F= 2n ( 2n + 1 ) / 2 + 1 - 2n;2)贪心算法:在对问题求解时,总是作出在当前看来是最好的选择。
也就是说,不从整体上加以考虑,它所作出的仅仅是在某种意义上的局部最优解(是否是全局最优,需要证明)。
贪心算法的基本步骤包括1、从问题的某个初始解出发。
2、采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或规模。
3、将所有部分解综合起来,得到问题的最终解。
例题1已知N个事件的发生时刻和结束时刻(见下表,表中事件已按结束时刻升序排序)。
一些在时间上没有重叠的事件,可以构成一个事件序列,如事件{2,8,10}。
事件序列包含的事件数目,称为该事件序列的长度。
请编程找出一个最长的事件序列。
分析不妨用Begin[i]和End[i]表示事件i的开始时刻和结束时刻。
则原题的要求就是找一个最长的序列a1<a2<…<an,满足:Begin[a1]<End[a1]<=…<=Begin[an]<End[an];可以证明,如果在可能的事件a1<a2<…<an中选取在时间上不重叠的最长序列,那么一定存在一个包含a1(结束最早)的最长序列。
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 算法集
Prim
#include <iostream> using namespace std; #define M 2001 int set[M]={0},g[M][M]; char str[M][8]; inline void make_map(int n,int g[M][M]){ int i,j,k; for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ int c=0; for(k=0;k<7;k++) if(str[i][k]!=str[j][k]) c++; g[i][j]=g[j][i]=c; } } } int main(){ int n,q[M],qf=0,ql=0,d[M],u; char c; scanf("%d%c",&n,&c);
int i; while(n!=0){ memset(set,0,sizeof(set)); memset(g,0,sizeof(g)); for(i=1;i<=n;i++) { scanf("%s",&str[i]); q[i-1]=i; d[i]=2000000; } qf=0;ql=n-1; make_map(n,g); int sum=0; int f=false; while(qf<=ql){ int min=qf; for(i=qf+1;i<=ql;i++){ if(d[q[i]] < d[q[min]]) min=i; } swap(q[qf],q[min]); u=q[qf]; qf++; if(f) sum+=d[u]; for(i=1;i<=n;i++){ if(g[u][i] !=0 && g[u][i] < d[i]) d[i]=g[u][i]; } f=true; } printf("The highest possible quality is 1/%d.\n",sum); scanf("%d%c",&n,&c); } return 0; }
ACM经典算法之字符串处理:字符串替换
ACM经典算法之字符串处理:字符串替换语法:replace(char str[],char key[],char swap[]);參数:str[]:在此源字符串进⾏替换操作key[]:被替换的字符串,不能为空串swap[]:替换的字符串,能够为空串,为空串表⽰在源字符中删除key[]返回值:null注意:默认str[]长度⼩于1000,如否,⼜⼀次设定设定tmp⼤⼩须要 string.h源程序:#include<stdio.h>#include<string.h>void replace(char str[],char key[],char swap[]){int l1,l2,l3;int i,j;int 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++)//注意是⼩写的l⽽不是数字1{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);}}}int main(){char str[] ="I have a dream";char key[] ="have";char swap[]="Love";printf("原字符串是%s\n被替换的⼦串%s,替换为%s\n",str,key,swap);replace(str,key,swap);puts("替换后的字符串是:");puts(str);return 0;}。
ACM常用算法
ACM小组内部预定函数Ver 2.0 by IcyFenix 数学问题: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[]: 结果,用字符串表示注意:默认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: 需要转换到的进制数注意:高于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[],doublefi[],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,floaty3);参数:x1~3: 三角形3个顶点x坐标y1~3: 三角形3个顶点y坐标返回值: 三角形面积注意:需要 math.h源程序:float area3(float x1,float y1,float x2,float y2,floatx3,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,floatz2){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) 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.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<MAX( 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)return 1; 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);参数:PointSet输入的点集[]: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<PointSet[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],PointSet[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 answer is :%ld\n",i+1,(e+i*(n/d))%n);}}5.求解模线性方程组(中国余数定理)语法:result=Modular_Expoent(int a,int b,int n);参数:B[]、a=B[] (mod W[]) 的对应参数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[],intsuccess);参数: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[],intsuccess){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.顺序队列。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
① 若cs>d,则为不可行解,剪去相应子树,返回到i-1层继续执行;
② 若ws>=bestw,则不是最优解,剪去相应子树,返回到i-1层继续执行;
③ 若i >n,则算法搜索到一个叶结点,用bestw对最优解进行记录,返回到
i-1层继续执行;
④ 采用for循环对部件i从m个不同的供应商购得的情况进行讨论(1≤j≤m):
2、题目分析:
考虑到每种物品只有2 种选择,即装入背包或不装入背包,并且物品数和背包容量已给定,要计算装入背包物品的最大价值和最优装入方案,可用回溯法搜索子集树的算法进行求解。
3、算法设计:
a. 物品有n种,背包容量为C,分别用p[i]和w[i]存储第i种物品的价值和重量,用
x[i]标记第i种物品是否装入背包,用bestx[i]存储第i种物品的最优装载方案;
b. 用函数cover()判断图G 是否被顶点覆盖(用t标记):
① 初始t=0;
② 采用while循环对每个顶点i(1≤i≤n)进行讨论:
1> 若顶点i不在顶点覆盖集中(即c[i]==0),则查找与之有边连接的顶点j(即e[i][j]==1),判断所有顶点j:
若存在顶点j在顶点覆盖集中(即c[j]==0),则t=1;
1> 调用递归函Knapsack(i+1,cs+c[i][j],ws+w[i][j])对部件i+1进行购买;
2> 当j>m时for循环结束;
⑤ 当i=1时,若已测试完所有购买方案,外层调用就全部结束;
c. 主函数调用一次Knapsack(1,0,0)即可完成整个回溯搜索过程,最终得到的bestw
{
t=0;
if(c[i]==0)
{
j=1;
while(j<i)
{
if(e[j][i]==1&&c[j]==1)
t=1;
j++;
}
j++;
while(j<=n)
{
if(e[i][j]==1&&c[j]==1)
t=1;
j++;
}
void Backtrack(int i,int cp,int cw)
{
int j;
if(i>n)
{
if(cp>bestp)
{
bestp=cp;
for(i=0;i<=n;i++)
bestx[i]=x[i];
}
}
else
for(j=0;j<=1;j++)
{
x[i]=j;
if(cw+x[i]*w[i]<=c)
{
cw+=w[i]*x[i];
cp+=p[i]*x[i];
Backtrack(i+1,cp,cw);
cw-=w[i]*x[i];
cp-=p[i]*x[i];
}
}
}
main()
{
int i;
① 若s>=bestw,则不是最优解,剪去相应子树,返回到i-1层继续执行;
② 若i >n,则算法搜索到一个叶结点,调用函数cover()对图G进行判断:
若cover()为真,则用bestw对最优解进行记录,返回到i-1层继续执行;
③ 对顶点i分在与不在顶点覆盖集中两种情况进行讨论:
2、题目分析:
考虑到每个顶点有在与不在顶点覆盖集中两种情况,并且每个顶点的权值已给定,
要计算最小权顶点覆盖的顶点权之和,可用回溯法搜索子集树的算法进行求解。
3、算法设计:
a. 给定的图G 有n 个顶点和m条边,用w[i]存储顶点i的权值,用e[i][j]标记两顶
点为i和j的边是否存在,用c[i]标记顶点i是否在顶点覆盖集中;
if(cs>d)
return;
else if(ws>=bestw)
return;
else if(i>n)
{
bestw=ws;
return;
}
else
{
for(j=1;j<=m;j++) Knapsack(i+1,cs+c[i][j],ws+w[i][j]);
bestp=0;
scanf("%d%d",&n,&c);
for(i=1;i<=n;i++)
scanf("%d",&p[i]);
for(i=1;i&l("%d",&w[i]);
Backtrack(1,0,0);
printf("Optimal value is\n");
实验十三 最小重量机器设计问题
1、问题描述:
? 设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设 wij 是从供应商j 处购得的部件i的重量,cij 是相应的价格,给出总价格不超过d的最小重量机器设计。
2、题目分析:
考虑到从每一处供应商购得每一种部件的重量和相应价格以及总价格的上限已给定,要设计最小重量机器方案计算最小重量,可用回溯法搜索排列树的算法进行求解。
if(t==0)
return 0;
}
i++;
}
return 1;
}
void cut(int i,int s)
{
if(s>=bestw)
return;
if(i>n)
{
if(cover())
bestw=s;
return;
}
c[i]=0;
递归函数Knapsack(i,cs,ws)遍历排列树的时间复杂度为O(n!);主函数的双重for
循环的时间复杂度为O(mn), 且主函数调用递归函数Knapsack(1,0,0),故该算法的时
间复杂度为O(n!)。
实验十四 最小权顶点覆盖问题
1、问题描述:
? 给定一个赋权无向图G=(V,E),每个顶点v∈V都有一个权值w(v)。如果U包含于V,且对于(u,v)∈E 有u∈U 且v∈V-U,则有v∈K.如:U = {1}, 若有边(1,2), 则有2属于K. 若有集合U包含于V使得U + K = V, 就称U 为图G 的一个顶点覆盖。G 的最小权顶点覆盖是指G 中所含顶点权之和最小的顶点覆盖。
cut(i+1,s);
c[i]=1;
cut(i+1,s+w[i]);
}
main()
{
int i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&w[i]);
c[i]=0;
}
for(i=1;i<=n;i++)
1> 若顶点i不在顶点覆盖集中(即c[i]==0),则调用函数cut(i+1,s);
2> 若顶点i在顶点覆盖集中(即c[i]==1),则调用函数cut(i+1,s+w[i]);
④ 当i=1时,若已测试完所有顶点覆盖方案,外层调用就全部结束;
d. 主函数调用一次cut(1,0)即可完成整个回溯搜索过程,最终得到的bestw即为所
求最小顶点权之和。
4、源程序:
#include<stdio.h>
#define MIN 100000
int m,n,u,v,bestw;
int e[100][100],w[100],c[100];
int cover()
{
int i,j,t;
i=1;
while (i<=n)
装载方案(即bestx[i]=x[i]( 1≤i≤n));
② 采用for循环对物品i装与不装两种情况进行讨论(0≤j≤1):
1> x[i]=j;
2> 若总重量不大于背包容量(即cw+x[i]*w[i]<=c),则更新当前总价
值和总重量(即cw+=w[i]*x[i],cp+=p[i]*x[i]), 对物品i+1调用递归函
数Backtrack(i+1,cp,cw) 继续进行装载;
3> 函数Backtrack(i+1,cp,cw)调用结束后则返回当前总价值和总重量
(即 cw-=w[i]*x[i],cp-=p[i]*x[i]);
4> 当j>1时,for循环结束;
③ 当i=1时,若已测试完所有装载方案,外层调用就全部结束;
c. 主函数调用一次backtrack(1,0,0)即可完成整个回溯搜索过程,最终得到的bestp和bestx[i]即为所求最大总价值和最优装载方案。
4、源程序:
#include<stdio.h>
int n,c,bestp;
int p[10000],w[10000],x[10000],bestx[10000];
3、算法设计:
a. 部件有n个,供应商有m个,分别用w[i][j]和c[i][j]存储从供应商j 处购得的部