扩栈
#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); }
- lower_bound()
返回:有序表中最左边的value的it,若不存在返回第1个大于value的it。
形式:同binary_search()
- 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)即为所求