ACM模板
并查集--------------------------------------------------------------------------------------( 2 )
母函数--------------------------------------------------------------------------------------( 3 )
几何模板-----------------------------------------------------------------------------------( 3 )
二分匹配-----------------------------------------------------------------------------------( 6 )
最短路径-----------------------------------------------------------------------------------( 7 )
多重背包二进制模板(01背包)----------------------------------------------------( 8 )
qsort排序---------------------------------------------------------------------------------( 9 )
C++ sort排序-----------------------------------------------------------------------------( 11 )
三分查找-----------------------------------------------------------------------------------( 12 )
搜索-----------------------------------------------------------------------------------------( 12 )
string---------------------------------------------------------------------------------------( 15 )
map-----------------------------------------------------------------------------------------( 16 )
几何公式-----------------------------------------------------------------------------------( 16 )
组合公式-----------------------------------------------------------------------------------( 19 )
筛选法(素数)--------------------------------------------------------------------------( 19 )
最大连续子序列--------------------------------------------------------------------------( 20 )
set------------------------------------------------------------------------------------------( 20 )
并查集(HDU 1233)
#include<iostream>
#include<algorithm>
using namespace std;
int sum,h[55000],root[55000];
struct sj
{
int a,b,len;
}q[55000];
bool cmp(sj a,sj b)
{
return a.len<b.len;
}
int find(int x)
{
while(x!=root[x])
x=root[x];
return x;
}
void hebin(int x,int y,int k)
{
sum+=k;
if(h[x]>h[y])
root[y]=x;
else
{
if(h[x]<h[y])
root[x]=y;
else
root[y]=x,h[x]++;
}
}
main()
{
int m,n,i,fx,fy;
while(cin>>n&&n)
{
sum=0;
m=(n*(n-1))/2;
for(i=1;i<=m;i++)
{
cin>>q[i].a>>q[i].b>>q[i].len;
h[i]=1,root[i]=i;
}
sort(q+1,q+m+1,cmp);
for(i=1;i<=m;i++)
{
fx=find(q[i].a),fy=find(q[i].b);
if(fx!=fy)
hebin(fx,fy,q[i].len);
}
cout<<sum<<endl;
}
}
母函数(1028)
#include <iostream>
using namespace std;
const int lmax=300;
int c1[lmax+1],c2[lmax+1];
main()
{
int n,i,j,k;
while(cin>>n&&n!=0)
{
for(i=0;i<=n;i++)
c1[i]=1,c2[i]=0;
for(i=2;i<=n;i++)
{
for(j=0;j<=n;j++)
for (k=0;k+j<=n;k+=i)
c2[j+k]+=c1[j];
for (j=0;j<=n;j++)
c1[j]=c2[j],c2[j]=0;
}
cout<<c1[n]<<endl;
}
}
几何模板(1086)
#include<stdio.h>
#define max(a,b) a>b?a:b
#define min(a,b) a>b?b:a
struct Point
{
double x,y;
};
struct line
{
Point s;
Point e;
};
line node[110];
double dir(Point p0,Point p1,Point p2)
{
return ((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}
bool on(Point pi, Point pj ,Point pk)
{
if(((min(pi.x,pj.x)<=pk.x)&&(max(pi.x,pj.x)>=pk.x))&&((min(pi.y,pj.y)<=pk.y)&&(max(pi.y,pj.x)>=pk.y)))
return true ;
else return false;
}
bool ATM(Point p1,Point p2,Point p3,Point p4)
{
double d1,d2,d3,d4;
d1=dir(p3,p4,p1);
d2=dir(p3,p4,p2);
d3=dir(p1,p2,p3);
d4=dir(p1,p2,p4);
if(d1*d2<0&&d3*d4<0) return true;
else if(d1==0&&on(p3,p4,p1)) return true;
else if(d2==0&&on(p3,p4,p2)) return true;
else if(d3==0&&on(p1,p2,p3)) return true;
else if(d4==0&&on(p1,p2,p3)) return true;
else return false;
}
main()
{
int sum,t,i,j;
while(scanf("%d",&t)==1&&t)
{
for(i=1;i<=t;i++)
scanf("%lf%lf%lf%lf",&node[i].s.x,&node[i].s.y,&node[i].e.x,&node[i].e.y);
sum=0;
for(i=1;i<=t;i++)
for(j=i+1;j<=t;j++)
{
if(ATM(node[i].s,node[i].e,node[j].s,node[j].e))
sum++;
}
printf("%d\n",sum);
}
return 0;
}
二分匹配(1083)
#include<iostream>
using namespace std;
#include<stdio.h>
#include<vector>
vector<int>map[1005];
int link[1005];
int flag[1005];
int num,n,p;
int find(int i)
{
int j;
for(j=0;j<map[i].size();j++)
{
if(flag[map[i][j]]==0)
{
flag[map[i][j]]=1;
if(link[map[i][j]]==-1||find(link[map[i][j]]))
{
link[map[i][j]]=i;
return 1;
}
}
}
return 0;
}
int main(void)
{
int a,b,z,i,j,t;
while(cin>>t)
{
while(t--)
{
cin>>n>>p;
for(i=1;i<=n;i++)
{
map[i].clear();
}
for(i=1;i<=n;i++)
{
cin>>b;
while(b--)
{
cin>>a;
map[i].push_back(a);
}
}
num=0;
memset(link,-1,sizeof(link));
for(i=1;i<=n;i++)
{
memset(flag,0,sizeof(flag));
if(find(i))
num++;
}
if(num==n) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}
最短路径(2544)
#include<iostream>
using namespace std;
int map[110][110], d[110], flag[110];
#define max 10000000;
main()
{
int n,m,a,b,c,i,j,v;
int min;
while(cin>>n>>m)
{
if(n==0&&m==0) return 0;
memset(flag,0,sizeof(flag));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
map[i][j]=max;
for(i=1;i<=m;i++)
{
cin>>a>>b>>c;
If(map[a][b]<c)
{
map[a][b]=c;
map[b][a]=c;
flag[a]=flag[b]=1;
}
}
for(i=1;i<=n;i++)
d[i]=map[1][i];
for(i=1;i<n;i++)
{
min=max;
for(j=1;j<=n;j++)
{
if(flag[j]==1&&min>d[j])
{
v=j;
min=d[j];
}
}
flag[v]=0;
for(j=1;j<=n;j++)
{
if(flag[j]==1&&d[j]>d[v]+map[v][j])
d[j]=d[v]+map[v][j];
}
}
cout<<d[n]<<endl;
}
}
多重背包二进制模板(1059)
#include<iostream>
using namespace std;
#include<stdio.h>
bool dp[1<<20];
int num[10];
int main(void)
{
int m,n,i,j,t,left,k,count,sum,kk=1;
while(cin>>num[1]>>num[2]>>num[3]>>num[4]>>num[5]>>num[6])
{
if(num[1]+num[2]+num[3]+num[4]+num[5]+num[6]==0) return 0;
sum=0;
for(i=1;i<=6;i++)
sum+=num[i]*i;
if(sum%2==1)
{printf("Collection #%d:\nCan't be divided.\n\n",kk++);continue;}
for(i=1;i<=sum;i++)
dp[i]=false;
dp[0]=true;
for(i=1;i<=6;i++)
{
left=num[i];
for(k=1;k<=left;k<<=1)
{
t=k*i;
for(j=sum/2;j>=t;j--)
{
if(dp[j-t])
dp[j]=true;
}
left-=k;
}
if(left)
{
t=left*i;
for(j=sum/2;j>=t;j--)
{
if(dp[j-t])
dp[j]=true;
}
}
}
printf("Collection #%d:\n",kk++);
if(dp[sum/2]) printf("Can be divided.\n");
else printf("Can't be divided.\n");
cout<<endl;
}
}
01背包
for i=1..N
for v=V..0
f[v]=max{f[v],f[v-c[i]]+w[i]};
qsort排序
#include<stdilib.h>
一、对int类型数组排序
int num[100];
Sample:
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
}
qsort(num,100,sizeof(num[0]),cmp);
二、对char类型数组排序(同int类型)
char word[100];
Sample:
int cmp( const void *a , const void *b )
{
return *(char *)a - *(char *)b;
}
qsort(word,100,sizeof(word[0]),cmp);
三、对double类型数组排序(特别要注意)
double in[100];
int cmp( const void *a , const void *b )
{
return *(double *)a > *(double *)b ? 1 : -1;
}
qsort(in,100,sizeof(in[0]),cmp);
四、对结构体一级排序
struct In
{
double data;
int other;
}s[100]
//按照data的值从小到大将结构体排序,关于结构体内的排序关键数据data的类型可以很多种,参考上面的例子写
int cmp( const void *a ,const void *b)
{
return (*(In *)a).data > (*(In *)b).data ? 1 : -1;
}
qsort(s,100,sizeof(s[0]),cmp);
五、对结构体二级排序
struct In
{
int x;
int y;
}s[100];
//按照x从小到大排序,当x相等时按照y从大到小排序
int cmp( const void *a , const void *b )
{
struct In *c = (In *)a;
struct In *d = (In *)b;
if(c->x != d->x) return c->x - d->x;
else return d->y - c->y;
}
qsort(s,100,sizeof(s[0]),cmp);
六、对字符串进行排序
struct In
{
int data;
char str[100];
}s[100];
//按照结构体中字符串str的字典顺序排序
int cmp ( const void *a , const void *b )
{
return strcmp( (*(In *)a)->str , (*(In *)b)->str );
}
qsort(s,100,sizeof(s[0]),cmp);
七、计算几何中求凸包的cmp
int cmp(const void *a,const void *b) //重点cmp函数,把除了1点外的所有点,旋转角度排序
{
struct point *c=(point *)a;
struct point *d=(point *)b;
if( calc(*c,*d,p[1]) < 0) return 1;
elseif(!calc(*c,*d,p[1])&&dis(c->x,c->y,p[1].x,p[1].y)<dis(d->x,d->y,p[1].x,p[1].y)) //如果在一条直线上,则把远的放在前面
return 1;
else return -1;
}
sort
Sort排序
头文件
#include<iostream>
using namespace std;
#include<algotihm>
对数组int a[100]进行排序
bool cmp (int a,int b)
{ return a>b} 从大到小 反之则是从小到大
int main(void)
{
sort(a,a+n,cmp);数组的起始位置,数组的末尾位置,排序函数;
}
三分查找
搜索(1010)
1.使用queue
#include<iostream>
using namespace std;
#include<queue>
#include<stdio.h>
int mapt[60][60][60];
int flag[60][60][60];
int dir[6][3]={{0,0,1},{0,0,-1},{0,-1,0},{0,1,0},{1,0,0},{-1,0,0}};
struct ss
{
int x,y,z,time;
};
int A,B,C,T;
void dfs()
{
int i,j,k;
flag[1][1][1]=1;
ss temp,p;
queue<ss>q;
p.x=p.y=p.z=1;
p.time=0;
q.push(p);
while(!q.empty())
{
p=q.front();
q.pop();
for(i=0;i<6;i++)
{
temp=p;
temp.x+=dir[i][0];
temp.y+=dir[i][1];
temp.z+=dir[i][2];
temp.time=p.time+1;
if(temp.x<1||temp.x>A||temp.y<1||temp.y>B||temp.z<1||temp.z>C||mapt[temp.x][temp.y][temp.z]==1)
continue;
if(temp.x==A&&temp.y==B&&temp.z==C)
{
if(T>=temp.time)
{
cout<<temp.time<<endl;
}
else
cout<<"-1"<<endl;
return ;
}
if(flag[temp.x][temp.y][temp.z]==0&&mapt[temp.x][temp.y][temp.z]==0)
{
q.push(temp);
flag[temp.x][temp.y][temp.z]++;
}
}
}
cout<<"-1"<<endl;
}
int main(void)
{
int ww,t,i,j,k;
cin>>t;
while(t--)
{
cin>>A>>B>>C>>T;
memset(flag,0,sizeof(flag));
ww=0;
for(i=1;i<=A;i++)
for(j=1;j<=B;j++)
for(k=1;k<=C;k++)
{
scanf("%d",&mapt[i][j][k]);
if(!mapt[i][j][k]) ww++;
}
if(A+B+C+1>ww)
cout<<"-1"<<endl;
else
dfs();
}
return 0;
}
2.不使用queue
# include <iostream.h>
# include <string.h>
# include <stdlib.h>
char map[9][9];
int n,m,t,di,dj;
bool escape;
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
void dfs(int si,int sj,int cnt)
{ int i,temp;
if(si>n||sj>m||si<=0||sj<=0) return;
if(cnt==t&&si==di&&sj==dj) escape=1;
if(escape) return;
temp=(t-cnt)-abs(si-di)-abs(sj-dj);
if(temp<0||temp&1) return;
for(i=0;i<4;i++){
if(map[si+dir[i][0]][sj+dir[i][1]]!='X')
{
map[si+dir[i][0]][sj+dir[i][1]]='X';
dfs(si+dir[i][0],sj+dir[i][1],cnt+1);
map[si+dir[i][0]][sj+dir[i][1]]='.';
}
}
return;
}
int main()
{
int i,j,si,sj;
while(cin>>n>>m>>t)
{
if(n==0&&m==0&&t==0) break;
int wall=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='S') { si=i; sj=j; }
else if(map[i][j]=='D') { di=i; dj=j; }
else if(map[i][j]=='X') wall++;
}
if(n*m-wall<=t)
{
cout<<"NO"<<endl;
continue;
}
escape=0;
map[si][sj]='X';
dfs(si,sj,0);
if(escape) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
string
数组赋值
memset(s,0,sizeof(s)) 其中s为定义了的数组名
返回字符串长度
strlen(s);
字符串比较函数
strcmp(a,b) 若相同则返回0;
数组拷贝函数
strcpy(a,b) b拷贝至a
Map
#include<iostream>
using namespace std;
#include<map>
#include<string>
int main(void)
{
map<string,int>aa;
map<string,int>::iterator it;
string c;
int t,i;
aa.clear();
cin>>t;
while(t--)
{
cin>>c;
aa[c]++;
}
if(aa.find(2)!=aa.end())
{
cout<<aa[2];
}
for(it=aa.begin();it!=aa.end();it++)
{
cout<<it->first<<" "<<it->second<<endl;
}
}
几何公式
三角形:
1. 半周长P=(a+b+c)/2
2. 面积S=aHa/2=absin(C)/2=sqrt(P(P-a)(P-b)(P-c))
3. 中线Ma=sqrt(2(b^2+c^2)-a^2)/2=sqrt(b^2+c^2+2bccos(A))/2
4. 角平分线Ta=sqrt(bc((b+c)^2-a^2))/(b+c)=2bccos(A/2)/(b+c)
5. 高线Ha=bsin(C)=csin(B)=sqrt(b^2-((a^2+b^2-c^2)/(2a))^2)
6. 内切圆半径r=S/P=asin(B/2)sin(C/2)/sin((B+C)/2)
=4Rsin(A/2)sin(B/2)sin(C/2)=sqrt((P-a)(P-b)(P-c)/P)
=Ptan(A/2)tan(B/2)tan(C/2)
7. 外接圆半径R=abc/(4S)=a/(2sin(A))=b/(2sin(B))=c/(2sin(C))
四边形:
D1,D2 为对角线,M 对角线中点连线,A 为对角线夹角
1. a^2+b^2+c^2+d^2=D1^2+D2^2+4M^2
2. S=D1D2sin(A)/2
(以下对圆的内接四边形)
3. ac+bd=D1D2
4. S=sqrt((P-a)(P-b)(P-c)(P-d)),P 为半周长
正n 边形:
R 为外接圆半径,r 为内切圆半径
1. 中心角A=2PI/n
2. 内角C=(n-2)PI/n
3. 边长a=2sqrt(R^2-r^2)=2Rsin(A/2)=2rtan(A/2)
4. 面积S=nar/2=nr^2tan(A/2)=nR^2sin(A)/2=na^2/(4tan(A/2))
圆:
1. 弧长l=rA
2. 弦长a=2sqrt(2hr-h^2)=2rsin(A/2)
3. 弓形高h=r-sqrt(r^2-a^2/4)=r(1-cos(A/2))=atan(A/4)/2
4. 扇形面积S1=rl/2=r^2A/2
5. 弓形面积S2=(rl-a(r-h))/2=r^2(A-sin(A))/2
棱柱:
1. 体积V=Ah,A 为底面积,h 为高
2. 侧面积S=lp,l 为棱长,p 为直截面周长
3. 全面积T=S+2A
棱锥:
1. 体积V=Ah/3,A 为底面积,h 为高
(以下对正棱锥)
2. 侧面积S=lp/2,l 为斜高,p 为底面周长
3. 全面积T=S+A
棱台:
1. 体积V=(A1+A2+sqrt(A1A2))h/3,A1.A2 为上下底面积,h 为高
(以下为正棱台)
2. 侧面积S=(p1+p2)l/2,p1.p2 为上下底面周长,l 为斜高
3. 全面积T=S+A1+A2
圆柱:
7
1. 侧面积S=2PIrh
2. 全面积T=2PIr(h+r)
3. 体积V=PIr^2h
圆锥:
1. 母线l=sqrt(h^2+r^2)
2. 侧面积S=PIrl
3. 全面积T=PIr(l+r)
4. 体积V=PIr^2h/3
圆台:
1. 母线l=sqrt(h^2+(r1-r2)^2)
2. 侧面积S=PI(r1+r2)l
3. 全面积T=PIr1(l+r1)+PIr2(l+r2)
4. 体积V=PI(r1^2+r2^2+r1r2)h/3
球:
1. 全面积T=4PIr^2
2. 体积V=4PIr^3/3
球台:
1. 侧面积S=2PIrh
2. 全面积T=PI(2rh+r1^2+r2^2)
3. 体积V=PIh(3(r1^2+r2^2)+h^2)/6
球扇形:
1. 全面积T=PIr(2h+r0),h 为球冠高,r0 为球冠底面半径
2. 体积V=2PIr^2h/3
组合公式
1. C(m,n)=C(m,m-n)
2. C(m,n)=C(m-1,n)+C(m-1,n-1)
derangement D(n) = n!(1 - 1/1! + 1/2! - 1/3! + ... + (-1)^n/n!)
= (n-1)(D(n-2) - D(n-1))
Q(n) = D(n) + D(n-1)
求和公式,k = 1..n
1. sum( k ) = n(n+1)/2
2. sum( 2k-1 ) = n^2
3. sum( k^2 ) = n(n+1)(2n+1)/6
4. sum( (2k-1)^2 ) = n(4n^2-1)/3
5. sum( k^3 ) = (n(n+1)/2)^2
6. sum( (2k-1)^3 ) = n^2(2n^2-1)
7. sum( k^4 ) = n(n+1)(2n+1)(3n^2+3n-1)/30
8. sum( k^5 ) = n^2(n+1)^2(2n^2+2n-1)/12
9. sum( k(k+1) ) = n(n+1)(n+2)/3
10. sum( k(k+1)(k+2) ) = n(n+1)(n+2)(n+3)/4
12. sum( k(k+1)(k+2)(k+3) ) = n(n+1)(n+2)(n+3)(n+4)/5
筛选法(素数)
for(i=2;i*i<=n;i++)
if(p[i]==0)
for(j=i*i;j<=n;j+=i)
p[j]=1;
最大连续子序列(1231)
#include<stdio.h>
int sta,ed,n,j,sum,maxsum,ut[100001],b;
main()
{
while(scanf("%d",&n),n)
{
sum=0;maxsum=-999;
for(b=j=1;j<=n;j++)
{
scanf("%d",&in1[j]);
sum+=ut[j];
if(sum>maxsum)
{
maxsum=sum;
ed=j;
sta=b;
}
if(sum<0)
{
sum=0;
b=j+1;
}
}
if(maxsum<0)
printf("0 %d %d\n",ut[1],ut[n]);
else
printf("%d %d %d\n",maxsum,ut[sta],ut[ed]);
}
}
set
#include<iostream>
using namespace std;
#include<string>
#include<set>
int main(void)
{
set<string>ac;
set<string>wa;
set<string>::iterator it;
int tt,t,n;
string a,b;
cin>>t;
while(t--)
{
cin>>n;
ac.clear();
wa.clear();
while(n--)
{
cin>>tt>>a>>b;
if(tt>=0&&tt<=300)
{
if(b=="Accept")
{
if(wa.find(a)!=wa.end())
wa.erase(a);
ac.insert(a);
}
else
{
if(ac.find(a)==ac.end())
wa.insert(a);
}
}
cout<<"Accept: ";
for(it=ac.begin();it!=ac.end();it++)
cout<<*it;
cout<<endl;
cout<<"Wrong: ";
for(it=wa.begin();it!=wa.end();it++)
cout<<*it;
cout<<endl;
cout<<endl;
}
}
return 0;
}