ACM整理

扩栈

#pragma comment(linker, "/STACK:1024000000,1024000000")

文件

freopen("g:\\in2.in","r",stdin);

输入输出:

string←→char*

strcpy(ca,sa.c_str())

sa.assign(ca)

 

ios:width() fill()

  char prev;

  cout.width (10);//宽度10,默认空格字符填充

  cout << 40 << endl;//        40

  prev = cout.fill ('x');//修改为用x填充,prev为修改之前的填充字符

  cout.width (10);

  cout << 40 << endl;//xxxxxxxx40

 

字符串流:

Stringstream//<sstream>

    string s;

    getline(cin,s)

    stringstream ss;

    ss<<s;

    while(ss>>a)

        cout<<a<<endl;

 

sscanf()读取指定格式的数据

//sscanf()  函数从一个字符串中读进与指定格式相符的数据.

#include<stdio.h>

int main()

{

       char buf[100];

       sscanf("iios/12DDWDFF@122","%*[^/]/%[^@]",buf);//获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中

       printf("%s\n",buf);

}

 

sprintf()函数输出指定格式字符串

//sprintf()  函数从一个字符串中输出与指定格式相符的数据到另一个字符串

#include<stdio.h>

int main()

{

       char s[100];

       sprintf(s,"%6.3f",3.1415626);

       printf("%s\n",s);

}

 

pair 类:

  pair <string,double> product1 ("tomatoes",3.25);

  pair <string,double> product2;

  pair <string,double> product3;

  product2.first = "lightbulbs";

  product2.second = 0.99;

  product3 = make_pair ("shoes",20.0);

串:

strtok()//字符串分割

例:char *pch = strtok (str," ,.-");

  while (pch)

  {

    printf ("%s\n",pch);

    pch = strtok (NULL, " ,.-");

  }

 

<functional>

greater<int> less<int>

 

<algorithm>

排列:

next_permutation()

       char str[210];

       int count=1;

       cin>>str;

       int len=strlen(str);

       sort(str,str+len);

       do

       {

              printf("%d %s\n",count++,str);

       }while(next_permutation(str,str+len));

 

二分查找:

1.binary_search()

返回:有序表中是否存在value

形式:

bool binary_search ( ForwardIterator first, ForwardIterator last,const T& value );

bool binary_search ( ForwardIterator first, ForwardIterator last,const T& value, Compare comp );

实质:调用lower_bound()

相等判定为:(!(a<b) && !(b<a)) 或 (!comp(a,b) && !comp(b,a))

comp样例:bool comp(int i,int j) { return (i<j); }

  1. lower_bound()

返回:有序表中最左边的value的it,若不存在返回第1个大于value的it。

形式:同binary_search()

  1. upper_bound()

返回:有序表中最右边的value的右边的it,若不存在返回第1个大于value的it。

形式:同binary_search()

例:

  int myints[] = {10, 10, 10, 20, 20, 20, 30, 30};

  vector<int> v(myints,myints+8);

  vector<int>::iterator low,up;

  low=lower_bound (v.begin(), v.end(), 20);

  up= upper_bound (v.begin(), v.end(), 20);

  cout << "lower_bound at position " << int(low- v.begin()) << endl;//3

  cout << "upper_bound at position " << int(up - v.begin()) << endl;//6

 

<queue>

优先队列:

自定义优先级:

      struct cmp

      {

            operator bool ()(int x, int y)

            {

                    return x > y; // x小的优先级高

            //return p[x] > p[y];表示p[i]小的优先级高

            }

      };

     priority_queue<int, vector<int>, cmp>q;//定义方法

     //其中,第二个参数为容器类型。第三个参数为比较函数。

结构体声明方式:

struct node

{     int x, y;

       friend bool operator < (node a, node b)

       {     return a.x > b.x; //结构体中,x小的优先级高

}};

priority_queue<node>q;//定义方法

//在该结构中,y为值, x为优先级。

//通过自定义operator<操作符来比较元素中的优先级。

 

<map>

字符串指针作为map的key:

map<char*, int, cmp> my;

比较函数:

struct cmp

{

   bool operator () (const char *s1, const char *s2) const

   {

       return strcmp(s1, s2) < 0;

   }

};

 

1.memset函数要<string.h>不能忘,否则编译错误。最好头文件全写上,比赛开始就全部打上去,免得忘掉。

2.编译器一定选C++0x(g++ 4.7.3),不要选C++(g++ 4.4.5),因为后者printf,scanf,EOF等都要<stdio.h>,否则编译错误。

3.

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#include <math.h>

#include <iostream>

#include <algorithm>

#include <functional>

#include <string>

#include <map>

#include <vector>

#include <list>

#include <queue>

#include <stack>

#include <set>

#include <iomanip>

#include <sstream>

#include <fstream>

using namespace std;

const double PI = acos(-1.0);

const double e = 2.7182818284590455? //e=1+1+1/2!+1/3!+…+1/n!

int main()

{

       return 0;

}

----------------------《算法整理.doc》------------------------------

目录:位运算 素数 大数 最短路径 并查集 背包 组合 KMP 公约数 几何

字典树:

#define MAX_WORD_NUM 20002//最大单词个数

#define MAX_CHAR_NUM 4//最大字符种数

struct TRIE{

       int val;

       TRIE* next[MAX_CHAR_NUM];

       TRIE(){

              val = 0;

              memset(next,0,sizeof(next));

}};

void delete_all_node(TRIE* T){

       for(int i=0;i<MAX_CHAR_NUM;i++)

              if(T) delete_all_node(T->next[i]);

       delete T;

}

int idx(char c) {return c-'a';}

void add_trie(TRIE* T, char word[])

{

       TRIE* p = T;

       for(int i = 0; word[i]; i++) {

              int c = idx(word[i]);

              if(p->next[c]==NULL) p->next[c] = new TRIE;

              p = p->next[c];

              //p->val++;

       }

       res[p->val]--;

       p->val++;//此时p指向单词结点。

       res[p->val]++;

}

位运算:

判断n是否是2的非负整数幂:(!(n&(n-1)))&&n

n Mod(2^k):n&((1<<k)-1)

素数

#define MAX 10000

int pa[MAX+1]={2,2};//0为素数,1为合数,否则为2。

int pb[MAX/2];//MAX以内素数表

int GetPrime()//筛选MAX以内的素数,记得调用函数!

{     int i,j,k=0,n=MAX/2;

       for(i=2;i<=n;i++)

              if(!pa[i])

              {

                     pb[k++]=i;//用于打素数表pb,不用可删去。

                     for(j=i+i;j<=MAX;j+=i) pa[j]=1;

              }

       for(;i<=MAX;i++) if(!pa[i]) pb[k++]=i; //用于打素数表pb,不用可删去。

       return k;//返回素数个数。

}

int is_prime(int n) {

  for(int i = 2; i*i <= n; i++)

    if(n % i == 0) return 0;

  return 1;

}

快速幂:

__int64 FastM(__int64 a, __int64 b, __int64 c)

{//a的b次对c取模

       __int64 t=a%c,sum=1;

       while(b)

       {

              if(b&1) sum=(sum*t)%c;

              t=(t*t)%c;

              b>>=1;

       }

       return sum;

}

 

大数相加

void add(char a[],char b[],char c[])

{//a,b,c是倒着存的,会改变a,b

       int l1,l2,l,i,r,t;

       l1=strlen(a);l2=strlen(b);

       l=max(l1,l2);

       r=0;

       for(i=0;i<l;i++)

       {

              if(i>=l1) a[i]='0';

              if(i>=l2) b[i]='0';

              t=r+a[i]+b[i]-'0'-'0';

              c[i]=t%10+'0';

              r=t/10;

       }

       if(r) c[i++]=r+'0';

       c[i]='\0';

}

string add(const string s1,const string s2)

{

    int j,l,la,lb;

    string max,min;

    max=s1;min=s2;

    if(s1.length()<s2.length()) {max=s2;min=s1;}

    la=max.size();lb=min.size();

    l=la-1;

    for(j=lb-1;j>=0;j--,l--) max[l] += min[j]-'0';

    for(j=la-1;j>=1;j--) if(max[j]>'9'){max[j]-=10;max[j-1]++;}

    if(max[0]>'9') {max[0]-=10;max='1'+max;}

    return max;

}

Dijkstra

#include <stdio.h>

int n=0; /*结点个数*/

int prev[100]; /*记录最短路径到i的前一个顶点*/

int s[101]; /**/

double a[100][100]; /*记录边的权值*/

double dist[100]; /*记录从源点到i的相应最短路径*/

#define MAX_VALUE 100000.0

void dijkstra(int v)

{

    int i,j;

    if(v<1 || v>n)

        return;

    /*初始设置*/

    for(i=1;i<=n;i++)

    {

        dist[i]=a[v][i]; /*初始时从源点到i的最短路径设为从源点到i的权值*/

        s[i]=1; /*s[i]=false*/

        if(dist[i]==MAX_VALUE)

            prev[i]=0; /*从源点到i没有通路*/

        else

            prev[i]=v; /*从源点到i有通路时,最短路径前一个结点设为源点*/

    }

    dist[v]=0; /*源点到源点的最短路径为0*/

    s[v]=0; /*s[v]=true*/ /*为下面循环中源点不参加比较做准备*/

    /*中心部分*/

       for(i=1;i<n;i++)

       {

        double temp=MAX_VALUE;

        int u=v;

        /*找出一个剩余结点中到源点最短的结点*/

        for(j=1;j<=n;j++)

        {

                     if((s[j]==1) && (dist[j]<temp)) /*如果该点不是源点并且源点到j点路径是最短*/

            {

                u=j; /*u记录最短路径的点*/

                temp=dist[j]; /*记录源点到j点的最短路径*/

            }

            s[u]=0; /*s[u]=true*/ /*u点是下面进行比较的点*/

            /*找出通过U点是否有更短的路径*/

            for(j=1;j<=n;j++)

            {

                            if((s[j]==1) && (a[u][j]<MAX_VALUE))

                            {

                                   double newdist=dist[u]+a[u][j];

                                   if(newdist<dist[j]) /*源点到u的路径+u到j的路径<源点到j的路径*/

                                   {

                                          dist[j]=newdist; /*更改源点到j的路径长度*/

                                          prev[j]=u; /*更改源点到j的最短路径中,j的前一个结点*/

}}} } }}

int main()

{

    int i,j,v;

    double temp;

    printf("Please input number of point:\n");

    scanf("%d",&n); /*输入结点的个数*/

    printf("Now input length i to j:\n");

    for(i=1;i<=n;i++)

    {

        for(j=1;j<=n;j++)

        {

            scanf("%lf",&a[i][j]); /*输入i-->j的权值*/

            if(a[i][j]==0.0)

                a[i][j]=MAX_VALUE; /*输入为0表示没有通路,改为最大值*/

            if(i==j)

                a[i][j]=0.0; /*i-->i的权值为0*/

       }}

       printf("Now input v point(0<point<=%d):\n",n);

    scanf("%d",&v); /*输入起始结点*/

    dijkstra(v);

    /*设置输出*/

    for(i=1;i<=n;i++)

    {

        if(i!=v && dist[i]<MAX_VALUE)

                     /*源点到源点;源点到某点最长路径为无穷大的都不需要输出*/

        {

            printf("\nfrom %d to %d,the shortest way is %lf far:\n%d",v,i,dist[i],i);

            j=i;

            while(j!=v)/*输出直到前一个结点为源点为止,倒序输出*/

            {

                j=prev[j];

                printf("<---%d",j);

}}}}

 

void Floyed()

{

       int i,j,k;

       double t;

       for(k=1;k<=n;k++)//编号1~n的顶点

              for(i=1;i<=n;i++)

                     for(j=1;j<=n;j++)

                     {

                            //if(a[i][k]<0 || a[k][j]<0 || tax[k]<0) continue;//小于0表示无穷大,可用INF 2147483647/2表示无穷大

                            t=a[i][k]+a[k][j];//+tax[k];

                            if(t<a[i][j])// || a[i][j]<0)

                            {

                                   a[i][j]=t;

                                   //pre[i][j]=pre[i][k];//记录路径,i->j的第2个点

                                   //或pre[i][j]=pre[k][j];//记录路径,i->j的最后第2个点,输出时要倒着输。

                            }

                            //else if(t==a[i][j] && pre[i][j]>pre[i][k])//如果相等,存字典序小的路径,此时上面要用pre[i][j]=pre[i][k];

                            //            pre[i][j]=pre[i][k];

                     }

}

---最小生成树1

/*void kruskal(Vertex V,Edge E)

 {

       sort(E,1,m);//将边按照权值排序

       for (t=1;t<=m;t++)

       {

               if( getfather(edge[t].u)!=getfather(edge[t].v) )

              {

                  //利用并查集判断两个顶点是否在同一集合内

                  tot=tot+edge[t].data;//计算权值和

                  Union(edge[t].u,edge[t].v);//合并顶点

                  k++;//合并次数

              }

        }

        if( k==n-1 )

              形成了一棵最小生成树;

       else

              不存在这样的最小生成树;

} */

#include <stdio.h>//并查集最小生成树

#include <stdlib.h>

#define MAX 200001

typedef struct

{

       int x, y;

       int w;

}node;

 

node e[MAX];

int rank[MAX];

int father[MAX];

int sum;

 

int cmp(const void *a, const void *b)

{

       return (*(node *)a).w - (*(node *)b).w;

}

void Init(int x)

{

    for(int i=0;i<x;i++)

       {

              father[i] = i;

              rank[i] = 0;

       }

}

int FindSet(int x)

{

       if (x != father[x])

       {

              father[x] = FindSet(father[x]);

       }

       return father[x];

}

 

void Union(int x, int y, int w)

{

      

       if (x == y) return;

       if (rank[x] > rank[y])

              father[y] = x;

       else

              father[x] = y;

       if (rank[x] == rank[y])

              rank[y]++;

       sum += w;//压缩路径 起到优化的作用;

}

int main(){

       int n,m, x, y, i;

       while(scanf("%d %d",&m, &n)!=EOF){

          if(m==0&&n==0) break;

        int max=0;

        for (i = 0; i < n; i++){

            scanf("%d %d %d", &e[i].x, &e[i].y, &e[i].w);

            max+=e[i].w;

        }

        Init(n);

        qsort(e, n, sizeof(node), cmp);

        sum = 0;

        for (i = 0; i < n; i++){

            x = FindSet(e[i].x);

            y = FindSet(e[i].y);

            if (x != y)

                    Union(x, y, e[i].w);

          }

        printf("%d\n", max-sum);

       }

       return 0;

}

---最小生成树2

Int prim()

{

       int vi[N];//标记数组

       int dis[N];//起点到各点的最短距离

       int i,j,t=0,k;

       for(i=0;i<n;i++)

       {

              vi[i]=0;

              dis[i]=a[x][i];//x表示起点

       }

       vi[0]=1;

    for(i=1;i<n;i++)//注意是n-1次

       {

              int min=INF;

              for(j=0;j<n;j++)

              {

                     if(min>dis[j]&&!vi[j])

                     {

                            min=dis[j];

                            k=j;

                     }

              }

              vi[k]=1;

              t+=min;

              for(j=0;j<n;j++)

              {

                     if(dis[j]>a[k][j]&&!vi[j])

                            dis[j]=a[k][j];

              }

       }

       return t;

}

 

并查集

int FindSet(int x)

{

       if(x!=bin[x])

       {

              bin[x]=FindSet(bin[x]);

       }

       return bin[x];

}

find3(x){

      r = x;

      while (set[r] != r) //循环结束,则找到根节点r

          r = set[r];      

      i = x;

      while (i != r) { //本循环修改查找路径中所有节点

          j = set[i];//记下i的父节点,以便下次继续修改

         set[i] = r;//将i节点的父节点修改为r

          i = j;//继续下一次

      }

}

merge3(a,b){

   if (height(a) == height(b)) {

       height(a) = height(a) + 1;

       set[b] = a;

   } else if (height(a) < height(b))

      set[a] = b;

   else 

      set[b] = a;  }

 

01背包:

int d[N],w[N],val[M],n,W;

void knapsack()

{

    int i,j;

    memset(val,0,sizeof(val));

    for(i=1;i<=n;i++)

        for(j=W;j>=1;j--)

            if(j>=w[i]&&val[j-w[i]]+d[i]>val[j])

                val[j]=val[j-w[i]]+d[i];

}

求组合数C(n,m)且n>=m

__int64 arr[MAXN+1][MAXN+1]={0};

void csh()

{

       int i;

       for(i=1;i<=MAXN;i++)

       {

              arr[i][0]=1;

              arr[i][1]=i;

       }

}

__int64 Com(int n,int m)

{

       if(n-m<m) m=n-m;

       if(arr[n][m]) return arr[n][m];

       return arr[n][m]=Com(n-1,m-1)+Com(n-1,m);

}

全排列

下一个next_permutation(a,a+4)

上一个prev_permutation

KMP

void get_next(string T)

{

       int j=next[0]=-1;

       int i=0;

       while(i<T.length()-1)

              if(j==-1 || T[i]==T[j])

                     next[++i]=++j;

              else

                     j=next[j];

}

int KMP(string s,string t,int pos)

{

       get_next(t);

       int i=pos,j=0;

       while(j<(int)t.length() && i<(int)s.length())

       {

              if(j==-1 || s[i]==t[j])

              {

                     i++;j++;

              }

              else

                     j=next[j];

       }

       if(j==t.length())

              return i-j;

       else

              return -1;

}

公约数公倍数:

int gcd(int a,int b)

{

       return a%b?gcd(b,a%b):b;

}

int lcm(int a,int b)

{

       return a/gcd(a,b)*b;

}

<stdlib.h>

double atof(const char *s)串转浮点(四舍五入)

int atoi(const char *s)串转整型

long int strtol(const char *s,NULL,int base)base进制的串s转换为十进制

itoa(int value,char *str,int base)十进制自然数value转换为base进制的串str

 

 

几何

#include <iostream>

#include <cstdio>

#include <cmath>

#include <algorithm>

using namespace std;

const double eps = 1e-10;

 

struct Point

{

       double x,y;

       Point(double x=0,double y=0):x(x),y(y){}

};

typedef Point Vector;

 

Vector operator + (Vector A,Vector B) { return Vector(A.x+B.x, A.y+B.y); }

Vector operator - (Vector A,Vector B) { return Vector(A.x-B.x, A.y-B.y); }

Vector operator * (Vector A,double p) { return Vector(A.x*p  , A.y*p  ); }

Vector operator / (Vector A,double p) { return Vector(A.x/p  , A.y/p  ); }

 

bool operator < (const Point& a,const Point& b) { return a.x<b.x || (a.x == b.x && a.y<b.y); }

int dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; }

bool operator == (const Point& a, const Point& b) { return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; }

double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }

double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }

double Length(Vector A) { return sqrt(Dot(A,A)); }

double Angle(Vector A, Vector B) { return acos(Dot(A,B) / Length(A) / Length(B)); }

 

凸包Andrew算法

int Convex_Hull(Point* p,int n,Point* ch)

{//输入点数组p,个数为n,输出点数组ch,返回凸包顶点数m。

       //输入不能有重复点,p数组顺序被破坏。

       //如果期望在凸包的边上有输入点,把两个<=改成<

       //在精度要求高时用dcmp比较。

       sort(p,p+n);//先比较x坐标,再比较y坐标。

       int i,k,m=0;

       for(i=0;i<n;i++)

       {

              while(m>1 && dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0 ) m--;

              ch[m++]=p[i];

       }

       for(k=m,i=n-2;i>=0;i--)

       {

              while(m>k && dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0 ) m--;

              ch[m++]=p[i];

       }

       if(n>1) m--;

       return m;

}

 

线段l1,l2是否相交

struct Point

{//点结构

       double x,y;

};

struct Segline

{//线段结构

       Point s,e;

};

double XProduct(Point p,Point p1,Point p2)

{//叉积判方向(p1,p2)*(p1,p)

       return (p2.x-p1.x)*(p.y-p1.y)-(p2.y-p1.y)*(p.x-p1.x);

}

int InBox(Point p,Segline l)

{//判断点p是否在线段l的矩形框内,框内或框上返回1,框外返回0

       if(min(l.s.x,l.e.x)<=p.x&&p.x<=max(l.s.x,l.e.x)&&min(l.s.y,l.e.y)<=p.y&&p.y<=max(l.s.y,l.e.y)) return 1;

       else return 0;

}

int Intersect(Segline l1,Segline l2)

{//判断线段l1,l2是否相交。相交(包括首尾相接)返回1,不相交返回0

       double d1=XProduct(l1.s,l2.s,l2.e);

       double d2=XProduct(l1.e,l2.s,l2.e);

       double d3=XProduct(l2.s,l1.s,l1.e);

       double d4=XProduct(l2.e,l1.s,l1.e);

       if(d1*d2<0 && d3*d4<0)

              return 1;

       if(fabs(d1)<INF && InBox(l1.s,l2))

              return 1;

       else if(fabs(d2)<INF && InBox(l1.e,l2))

              return 1;

       else if(fabs(d3)<INF && InBox(l2.s,l1))

              return 1;

       else if(fabs(d4)<INF && InBox(l2.e,l1))

              return 1;

       return 0;

}

三角形的内心:(角平分线交点)

三角形A(X1,Y1),B(X2,Y2),C(X3,Y3),内心(X,Y),则:

X = (aX1+bX2+cX3)/(a+b+c)

Y = (aY1+bY2+cY3)/(a+b+c)

三角形的外心:(中垂线交点)

Point circle_center(double x1,double y1, double x2, double y2, double x3, double y3)

{        

       Point res;       

    res.x=((y2-y1)*(y3*y3-y1*y1+x3*x3-x1*x1)-(y3-y1)*(y2*y2-y1*y1+x2*x2-x1*x1))/(2*(x3-x1)*(y2-y1)-2*((x2-x1)*(y3-y1)));

    res.y=((x2-x1)*(x3*x3-x1*x1+y3*y3-y1*y1)-(x3-x1)*(x2*x2-x1*x1+y2*y2-y1*y1))/(2*(y3-y1)*(x2-x1)-2*((y2-y1)*(x3-x1)));

       return res;

}

三角形的垂心(高线的交点)

三角形的重心(中线的交点)

x0 = (x1+x2+x3) / 3;

y0 = (y1+y2+y3) / 3;

多边形的重心

for(j=0;j<n;j++)

{

       a[j] = (x[j]*y[j+1]-x[j+1]*y[j])*0.5; );//计算每个三角形的面积

       s += a[j];

       xx += (x[j]+x[j+1])*a[j];//x坐标的重心

          yy  += (y[j]+y[j+1])*a[j];//y坐标的重心

}

x1 = xx/s/3;

y1 = yy/s/3;

(x1,y1)即为所求

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值