acm 算法模板 适合初学者使用【转】

2019-04-13 21:16发布

三角形面积计算 ……………………………………………………………………………………. 1
字典树模板 ………………………………………………………………………………………….. 2
求线段所在直线 ……………………………………………………………………………………. 3
求外接圆……………………………………………………………………………………………… 4
求内接圆……………………………………………………………………………………………… 5
判断点是否在直线上 ……………………………………………………………………………… 6
简单多边形面积计算公式 ……………………………………………………………………….. 7
stein算法求最大共约数 ………………………………………………………………………….. 8
最长递增子序列模板——o(nlogn算法实现)……………………………………………….. 9
判断图中同一直线的点的最大数量 ………………………………………………………….10
公因数和公倍数 ………………………………………………………………………………….. 11
已知先序中序求后序 ……………………………………………………………………………. 12
深度优先搜索模板……………………………………………………………………………….. 13
匈牙利算法——二部图匹配BFS实现……………………………………………………… 14
带输出路径的prime算法………………………………………………………………………. 15
prime模板………………………………………………………………………………………….. 16
kruskal模板 ………………………………………………………………………………………..17
dijsktra ………………………………………………………………………………………………. 18
并查集模板 ………………………………………………………………………………………… 19
高精度模板 ………………………………………………………………………………………… 20

三角形面积计算

//已知三条边和外接圆半径,公式为s = a*b*c/(4*R) double GetArea(double a, double b, double c, double R) { return a*b*c/4/R; } //已知三条边和内接圆半径,公式为s = pr double GetArea(double a, double b, double c, double r) { return r*(a+b+c)/2; } //已知三角形三条边,求面积 double GetArea(doule a, double b, double c) { double p = (a+b+c)/2; return sqrt(p*(p-a)*(p-b)*(p-c)); } //已知道三角形三个顶点的坐标 struct Point { double x, y; Point(double a = 0, double b = 0) { x = a; y = b; } }; double GetArea(Point p1, Point p2, Point p3) { double t = -p2.x*p1.y+p3.x*p1.y+p1.x*p2.y-p3.x*p2.y-p1.x*p3.y+p2.x*p3.y; if(t < 0) t = -t; return t/2; }

字典树模板

#include #include #include #define BASE_LETTER 'a' #define MAX_TREE 35000 #define MAX_BRANCH 26 struct { int next[MAX_BRANCH]; //记录分支的位置 int c[MAX_BRANCH]; //查看分支的个数 int flag; //是否存在以该结点为终止结点的东东,可以更改为任意的属性 }trie[MAX_TREE]; int now; void init() { now = 0; memset(&trie[now], 0, sizeof(trie[now])); now++; } int add () { memset(&trie[now], 0, sizeof(trie[now])); return now++; } int insert( char *str) { int pre = 0, addr; while( *str != 0 ) { addr = *str - BASE_LETTER; if( !trie[pre].next[addr] ) trie[pre].next[addr] = add(); trie[pre].c[addr]++; pre = trie[pre].next[addr]; str++; } trie[pre].flag = 1; return pre; } int search( char *str ) { int pre = 0, addr; while( *str != 0 ) { addr = *str - BASE_LETTER; if ( !trie[pre].next[addr] ) return 0; pre = trie[pre].next[addr]; str ++; } if( !trie[pre].flag ) return 0; return pre; } pku2001题,源代码: void check( char *str ) { int pre = 0, addr; while(*str != 0) { addr = *str - BASE_LETTER; if( trie[pre].c[addr] == 1) { printf("%c ", *str); return; } printf("%c", *str); str ++; } printf(" "); } char input[1001][25]; int main() { int i = 0,j; init(); while(scanf("%s", input[i]) != EOF) { getchar(); insert(input[i]); i++; } for(j = 0; j < i; j ++) { printf("%s ", input[j]); check(input[j]); } return 0; }

求线段所在直线

struct Line { double a, b, c; }; struct Point { double x, y; } Line GetLine(Point p1, Point p2) { //ax+by+c = 0返回直线的参数 Line line; line.a = p2.y - p1.y; line.b = p1.x - p2.x; line.c = p2.x*p1.y - p1.x*p2.y; return line; }

求外接圆

//已知三角形三个顶点坐标,求外接圆的半径和坐标 struct Point { double x, y; Point(double a = 0, double b = 0) { x = a; y = b; } }; struct TCircle { double r; Point p; } double distance(Point p1, Point p2) { return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); } double GetArea(doule a, double b, double c) { double p = (a+b+c)/2; return sqrt(p*(p-a)*(p-b)*(p-c)); } TCircle GetTCircle(Point p1, Point p2, Point p3) { double a, b, c; double xa, ya, xb, yb, xc, yc, c1, c2; TCircle tc; a = distance(p1, p2); b = distance(p2, p3); c = distance(p3, p1); //求半径 tc.r = a*b*c/4/GetArea(a, b, c); //求坐标 xa = p1.x; ya = p1.b; xb = p2.x; yb = p2.b; xc = p3.x; yc = p3.b; c1 = (xa*xa + ya*ya - xb*xb - yb*yb)/2; c2 = (xa*xa + ya*ya - xc*xc - yc*yc)/2; tc.p.x = (c1*(ya-yc) - c2*(ya-yb))/((xa-xb)*(ya-yc) - (xa-xc)*(ya-yb)); tc.p.y = (c1*(xa-xc) - c2*(xa-xb))/((ya-yb)*(xa-xc) - (ya-yc)*(xa-xb)); return tc; }

求内接圆

struct Point { double x, y; Point(double a = 0, double b = 0) { x = a; y = b; } }; struct TCircle { double r; Point p; } double distance(Point p1, Point p2) { return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); } double GetArea(doule a, double b, double c) { double p = (a+b+c)/2; return sqrt(p*(p-a)*(p-b)*(p-c)); } TCircle GetTCircle(Point p1, Point p2, Point p3) { double a, b, c; double xa, ya, xb, yb, xc, yc, c1, c2, f1, f2; double A,B,C; TCircle tc; a = distance(p1, p2); b = distance(p3, p2); c = distance(p3, p1); //求半径 tc.r = 2*GetArea(a, b, c)/(a+b+c); //求坐标 A = acos((b*b+c*c-a*a)/(2*b*c)); B = acos((a*a+c*c-b*b)/(2*a*c)); C = acos((a*a+b*b-c*c)/(2*a*b)); p = sin(A/2); p2 = sin(B/2); p3 = sin(C/2); xb = p1.x; yb = p1.b; xc = p2.x; yc = p2.b; xa = p3.x; ya = p3.b; f1 = ( (tc.r/p2)*(tc.r/p2) - (tc.r/p)*(tc.r/p) + xa*xa - xb*xb + ya*ya - yb*yb)/2; tc.p.x = (f1*(ya-yc) - f2*(ya-yb))/((xa-xb)*(ya-yc)-(xa-xc)*(ya-yb)); tc.p.y = (f1*(xa-xc) - f2*(xa-xb))/((ya-yb)*(xa-xc)-(ya-yc)*(xa-xb)); return tc; }

判断点是否在直线上

//判断点p是否在直线[p1,p2] struct Point { double x,y; }; bool isPointOnSegment(Point p1, Point p2, Point p0) { //叉积是否为0,判断是否在同一直线上 if((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y) != 0) return false; //判断是否在线段上 if((p0.x > p1.x && p0.x > p2.x) || (p0.x < p1.x && p0.x < p2.x)) return false; if((p0.y > p1.y && p0.y > p1.y) || (p0.y < p1.y && p0.y < p2.y)) return false; return true; }

简单多边形面积计算公式

struct Point { double x, y; Point(double a = 0, double b = 0) { x = a; y = b; } }; Point pp[10]; double GetArea(Point *pp, int n) { //n为点的个数,pp中记录的是点的坐标 int i = 1; double t = 0; for(; i <= n-1; i++) t += pp[i-1].x*pp[i].y - pp[i].x*pp[i-1].y; t += pp[n-1].x*pp[0].y - pp[0].x*pp[n-1].y; if(t < 0) t = -t; return t/2; }

stein算法求最大共约数

int gcd(int a,int b) { if (a == 0) return b; if (b == 0) return a; if (a % 2 == 0 && b % 2 == 0) return 2 * gcd(a/2,b/2); else if (a % 2 == 0) return gcd(a/2,b); else if (b % 2 == 0) return gcd(a,b/2); else return gcd(abs(a-b),min(a,b)); }

最长递增子序列模板——o(nlogn算法实现)

#include #define MAX 40000 int array[MAX], B[MAX]; int main() { int count,i,n,left,mid,right,Blen=0,num; scanf("%d",&count); //case的个数 while(count--) { scanf("%d",&n); //每组成员的数量 Blen = 0; for(i=1;i<=n;i++) scanf("%d",&array[i]); //读入每个成员 for(i=1;i<=n;i++) { num = array[i]; left = 1; right = Blen; while(left<=right) { mid = (left+right)/2; if(B[mid]1; else right = mid-1; } if(Blenprintf("%d ",Blen);//输出结果 } return 1; }

判断图中同一直线的点的最大数量

#include #include #include using namespace std; #define MAX 1010 //最大点的个数 struct point { int x,y; }num[MAX]; int used[MAX][MAX*2]; //条件中点的左边不会大于1000,just equal MAX int countN[MAX][MAX*2]; #define abs(a) (a>0?a:(-a)) int GCD(int x, int y) { int temp; if(x < y) { temp = x; x = y; } while(y != 0) { temp = y; y = x % y; x = temp; } return x; } int main() { int n,i,j; int a,b,d,ans; while(scanf("%d", &n)==1) { //inite ans = 1; memset(used, 0, sizeof(used)); memset(countN, 0, sizeof(countN)); //read for(i = 0; i < n; i++) scanf("%d%d", &num[i].x, &num[i].y); for(i = 0; i < n-1; i++) { for(j = i+1; j < n; j++) { b = num[j].y-num[i].y; a = num[j].x-num[i].x; if(a < 0) //这样可以让(2,3)(-2,-3)等价 { a = -a; b = -b; } d = GCD(a,abs(b)); a /= d; b /= d; b += 1000;//条件中点的左边不会大于1000 if(used[a][b] != i+1) { used[a][b] = i+1; countN[a][b] = 1; } else { countN[a][b]++; if(ans < countN[a][b]) ans = countN[a][b]; } }//for }//for printf("%d ", ans+1); } return 0; }

公因数和公倍数

int GCD(int x, int y) { int temp; if(x < y) { temp = x; x = y; y = temp; } while(y != 0) { temp = y; y = x % y; x = temp; } return x; } int beishu(int x, int y) { return x * y / GCD(x,y); }

已知先序中序求后序

#include #include using namespace std; string post; void fun(string pre, string mid) { if(pre == "" || mid == "") return; int i = mid.find(pre[0]); fun(pre.substr(1,i), mid.substr(0,i)); fun(pre.substr(i+1, (int)pre.length()-i-1),mid.substr(i+1, (int)mid.length()-i-1)); post += pre[0]; } int main() { string pre, mid; while(cin >> pre) { cin >> mid; post.erase(); fun(pre, mid); cout << post << endl; } return 0; }

深度优先搜索模板

int t; //t用来标识要搜索的元素 int count; //count用来标识搜索元素的个数 int data[m][n]; //data用来存储数据的数组 //注意,数组默认是按照1„„n存储,即没有第0行 //下面是4个方向的搜索, void search(int x, int y) { data[x][y] = *; //搜索过进行标记 if(x-1 >= 1 && data[x-1][y] == t) { count++; search(x-1,y); } if(x+1 <= n && data[x+1][y] == t) { count++; search(x+1,y); } if(y-1 >= 1 && data[x][y-1] == t) { count++; search(x,y-1); } if(y+1 <= n && data[x][y+1] == t) { count++; search(x,y+1); } } //下面是8个方向的搜索 void search(int x, int y) { data[x][y] = *; //搜索过进行标记 if(x-1 >= 1) { if(data[x-1][y] == t) { count++; search(x-1,y); } if(y-1 >= 1 && data[x-1][y-1] == t) { count++; search(x-1,y-1); } if(y+1 <= n && data[x-1][y+1] == t) { count++; search(x-1,y+1); } } if(x+1 <= n) { if(data[x+1][y] == t) { count++; search(x+1,y); } if(y-1 >= 1 && data[x+1][y-1] == t) { count++; search(x+1,y-1); } if(y+1 <= n && data[x+1][y+1] == t) { count++; search(x+1,y+1); } } if(y-1 >= 1 && data[x][y-1] == t) { count++; search(x,y-1); } if(y+1 <= n && data[x][y+1] == t) { count++; search(x,y+1); } }

匈牙利算法——二部图匹配BFS实现

//匈牙利算法实现 #define MAX 310 //二部图一侧顶点的最大个数 int n,m; //二分图的两个集合分别含有n和m个元素。 bool map[MAX][MAX]; //map存储邻接矩阵。 int Bipartite() { int i, j, x, ans; //n为最大匹配数 int q[MAX], prev[MAX], qs, qe; //q是BFS用的队列,prev是用来记录交错链的,同时也用来记录右边的点是否被找过 int vm1[MAX], vm2[MAX]; //vm1,vm2分别表示两边的点与另一边的哪个点相匹配 ans = 0; memset(vm1, -1, sizeof(vm1)); memset(vm2, -1, sizeof(vm2)); //初始化所有点为未被匹配的状态 for( i = 0; i < n; i++ ) { if(vm1[i] != -1)continue; //对于左边每一个未被匹配的点进行一次BFS找交错链 for( j = 0; j < m; j++ ) prev[j] = -2; //每次BFS时初始化右边的点 qs = qe = 0; //初始化BFS的队列 //下面这部分代码从初始的那个点开始,先把它能找的的右边的点放入队列 for( j = 0; j < m; j++ ) { if( map[i][j] ) { prev[j] = -1; q[qe++] = j; } } while( qs < qe ) { //BFS x = q[qs]; if( vm2[x] == -1 ) break; //如果找到一个未被匹配的点,则结束,找到了一条交错链 qs++; //下面这部分是扩展结点的代码 for( j = 0; j < m; j++ ) { if( prev[j] == -2 && map[vm2[x]][j] ) { //如果该右边点是一个已经被匹配的点,则vm2[x]是与该点相匹配的左边点 //从该左边点出发,寻找其他可以找到的右边点 prev[j] = x; q[qe++] = j; } } } if( qs == qe ) continue; //没有找到交错链 //更改交错链上匹配状态 while( prev[x] > -1 ) { vm1[vm2[prev[x]]] = x; vm2[x] = vm2[prev[x]]; x = prev[x]; } vm2[x] = i; vm1[i] = x; //匹配的边数加一 ans++; } return ans; }

带输出路径的prime算法

#include #include using namespace std; const int MAX = 110; int data[MAX][MAX]; int lowcost[MAX]; int adjvex[MAX]; int main() { int n; cin >> n; int i,j; for(i = 0 i < n; i++) for(j = 0; j < n; j++) cin >> data[i][j]; //prim for(i = 1; i < n; i++) { lowcost[i] = data[0][i]; adjvex[i] = 0; } for(i = 1; i < n; i++) { int min = 1<<25, choose; for(j = 1; j < n; j++) { if(lowcost[j] && lowcost[j] < min) { min = lowcost[j]; choose = j; } } printf("<%d %d> %d ",adjvex[choose]+1,choose+1, lowcost[choose]); lowcost[j] = 0; for(j = 1; j < n; j++) { if(lowcost[j] && lowcost[j] > data[choose][j]) { lowcost[j] = data[choose][j]; adjvex[j] = choose; } } } return0; }

prime模板

#include #include #include using namespace std; int const MAX = 110; int dis[MAX][MAX]; int lowcost[MAX]; int main() { int n; int i,j; while(cin >> n) { for(i = 0; i < n; i++) for(j = 0; j < n; j++) cin >> dis[i][j]; //下面是prim算法部分,ans是计算所有路径的和 lowcost[0] = 0; for(i = 1; i < n; i++) lowcost[i] = dis[0][i]; int ans = 0; for(i = 1; i < n; i++) { double min = (1<<30); int choose; for(j = 1; j < n; j++) { if(lowcost[j] != 0 && lowcost[j] < min) { min = lowcost[j]; choose = j; } } ans += lowcost[choose]; lowcost[choose] = 0; for(j = 1; j < n; j++) { if(lowcost[j] != 0 && lowcost[j]>dis[choose][j]) lowcost[j] = dis[choose][j]; } } cout << ans << endl; } return 0; }

kruskal模板

#include #include #include using namespace std; const int MAX = 1010; //节点个数 const int MAXEDGE = 15010; //边个数 bool used[MAXEDGE]; //标记边是否用过 struct node { int begin, end, dis; }data[MAXEDGE]; class UFSet { private: int parent[MAX+1]; public: UFSet(int s = MAX); int Find(int x); }; UFSet::UFSet(int s) { size = s+1; memset(parent, -1, sizeof(int)*size); } void UFSet::Union(int root1, int root2) { int temp = parent[root1] + parent[root2]; if(parent[root1] <= parent[root2]) { parent[root2] = root1; parent[root1] = temp; } else { parent[root1] = root2; parent[root2] = temp; } } int UFSet::Find(int x) { int p = x; while(parent[p] > 0) p = parent[p]; int t = x; while(t != p) { t = parent[x]; parent[x] = p; x = t; } return p; } bool cmp(node a, node b) { return (a.dis < b.dis); } int main() { int n, m; scanf("%d%d", &n, &m); int i,j; for(i = 0; i < m; i++) scanf("%d%d%d", &data[i].begin, &data[i].end, &data[i].dis); //最小生成树 UFSet ufs(n); sort(data, data+m, cmp); int root1, root2; int total = 0; for(i = 0; i < m; i++) { root1 = ufs.Find(data[i].begin); root2 = ufs.Find(data[i].end); if(root1 == root2) continue; ufs.Union(root1, root2); used[i] = true; total++; if(total == n-1) break; } printf("%d %d ", data[i].dis, n-1); for(j = 0; j <= i; j++) if(used[j]) printf("%d %d ", data[j].begin, data[j].end); return 0; }

dijsktra

#include #include using namespace std; const int maxint = 9999999; const int maxn = 1010; int data[maxn][maxn], lowcost[maxn]; //data存放点点之间的距离,lowcost存放点到start的距离,从0开始存放 bool used[maxn]; //标记点是否被选中 int n; //顶点的个数 void disktra(int start)//初始点是start的dij算法 { int i,j; memset(used, 0, sizeof(used)); //inite for(i = 0; i < n; i++) lowcost[i] = data[start][i]; used[start] = true; lowcost[start] = 0; for(i = 0; i < n-1; i++) { //choose min int tempmin = maxint; int choose; for(j = 0; j < n; j++) { if(!used[j] && tempmin > lowcost[j]) { choose = j; tempmin = lowcost[j]; } } used[choose] = true; //updata others for(j = 0; j < n; j++) { if(!used[j] && data[choose][j] < maxint && lowcost[choose]+data[choose][j] < lowcost[j]) lowcost[j] = lowcost[choose]+data[choose][j]; } } }

并查集模板

#include #include <memory> using namespace std; const int MAX = 5005; class UFSet { private: int parent[MAX+1]; int size; public: UFSet(int s = MAX);//初始化 void Union(int root1, int root2);//合并,注意参数为根节点 int Find(int i );//返回根节点 int SetNum();//返回集合的个数 }; UFSet::UFSet(int s) { size = s+1; memset(parent, -1, sizeof(int)*size ); } void UFSet::Union( int root1, int root2) { int temp = parent[root1]+parent[root2]; if(parent[root1]<parent[root2]) { parent[root2]=root1; parent[root1]=temp; } else { parent[root1]=root2; parent[root2]=temp; } } int UFSet::Find(int i) { int j; for(j = i; parent[j]>=0; j = parent[j]); while(i!=j) { int temp = parent[i]; parent[i] = j; i = temp; } return j; } int UFSet::SetNum() { int totalNum = 0,i; for(i = 0; i < size; i++) if(parent[i] < 0) totalNum++; return totalNum; }

高精度模板

#include #include using namespace std; // ----------------- 非负数计算部分:f1~f14 ------------------------------------- string operator+(string x, string y); // x、y都必须非负 string operator-(string x, string y); // x、y都必须非负(结果可能为负) string operator*(string x, string y); // x、y非负 string operator*(string s, int a); // s,a非负,且a必须小于2*10^8. string MSDiv(string x, int y, int &res); // 多精度除以int,x非负,y为正 string operator/(string s, int a); // 调用MSDiv int operator%(string s, int a); // 调用MSDiv string MMDiv(string x, string y, string &res); // 多精度除以多精度,x非负,y为正 string operator/(string x, string y); // 调用MMDiv string operator%(string x, string y); // 调用MMDiv string HPower(string s, int a); // s,a必须非负! string HSqrt(string s); // 开平方取整,s非负! string Head_zero_remover(string num); // 除了开头可能有'0'外,num必须是非负数。 bool Less(string x, string y); // 非负数之间的“小于” // ----------------- 以下是负数支持:f15~f19 ------------------------------------ string operator-(string s); // 取负 string SAdd(string x, string y); string SMinus(string x, string y); string SMul(string x, string y); string SMul(string s, int a); // 同样,a的绝对值不能超过2*10^8 // ----------------- f1 () -------------------------- string operator+(string x, string y) { if(x.size() < y.size()) // 预处理,保证x的实际长度>=y x.swap(y); y.insert(y.begin(), x.size()-y.size(), '0'); // y开头补0到和x一样长 string sum(x.size(), -1); // 初始大小:x.size() int carry=0; for(int i=x.size()-1; i >= 0; --i) { carry += x[i]+y[i]-2*'0'; sum[i] = carry%10+'0'; carry /= 10; } if(carry > 0) // 还有进位1 return string("1") += sum; // 给开头添加一个“1” return sum; } // ----------------- f2 (need: f13, f14) -------------------- string operator-(string x, string y) { bool neg = false; // 结果为负标志 if(Less(x, y)) { x.swap(y); // 如果x neg = true; // 结果标记为负 } string diff(x.size(), -1); // 差(结果) y.insert(y.begin(), x.size()-y.size(), '0'); int carry=0; for(int i=x.size()-1; i >= 0; --i) if(x[i] >= y[i]+carry) // 本位够减 { diff[i] = x[i]-y[i]-carry+'0'; carry = 0; } else // 需要借位 { diff[i] = 10+x[i]-y[i]-carry+'0'; carry=1; } if(neg) return string(