为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

ACM 算法模板2

2012-04-01 40页 doc 248KB 26阅读

用户头像

is_723096

暂无简介

举报
ACM 算法模板2哈嘻嘟-浙江省第七届程序设计-2010-4-17 目 录 2 一、图论 2 1.1.最小生成树类prim算法 4 1.2.拓扑排序 5 1.3.最短源路径Folyd实现 6 1.4.关键路径实现算法 8 1.5.二分图最大匹配的匈牙利算法 9 1.6.并查集 11 二、动规 11 2.1.求最长子序列 12 2.2.求解最长升序列长度及子序列 13 2.3.完全背包问题 14 2.4.0-1背包问题 15 2.5.母函数DP算法求组合数 17 2.6.滚动数组求回文...
ACM 算法模板2
哈嘻嘟-浙江省第七届程序-2010-4-17 目 录 2 一、图论 2 1.1.最小生成树类prim算法 4 1.2.拓扑排序 5 1.3.最短源路径Folyd实现 6 1.4.关键路径实现算法 8 1.5.二分图最大匹配的匈牙利算法 9 1.6.并查集 11 二、动规 11 2.1.求最长子序列 12 2.2.求解最长升序列长度及子序列 13 2.3.完全背包问 14 2.4.0-1背包问题 15 2.5.母函数DP算法求组合数 17 2.6.滚动数组求回文串问题 18 三、贪心 18 3.1.时间安排问题 19 3.2.求最大子段和 20 3.3.贪心求最少非递减序列数 21 四、数论 21 4.1.简单求Cnk问题 21 4.2.巧求阶乘位数 22 4.3.线性算法求素数 22 五、其他 22 5.1.采用位操作递归求解示例 23 5.2.Stack和Queue用法 24 5.3.map使用详解 25 5.4.字典树建立与查找 26 5.5.KMP匹配算法 28 5.6.后缀数组求最长连续公共子序列长度 30 5.7.循环字符串最小位置表示及同构判断 32 5.8.求哈夫曼树编码长度 34 5.9.堆排序算法 35 5.10.线段树着色问题 39 六、附: 39 6.1.C++最值常量 39 6.2.类型转换 39 6.3.String常用函数举例 40 6.4.C++常用头文件 一、图论 1.1.最小生成树类prim算法 1.1.1下标从1开始 #include #include #include using namespace std; #define SIZE 101 #define MAXSIZE 10201 int n,nline;/*n 个点,nline行关系*/ int in[SIZE]; struct Point{ int x,y;/*编号从1开始*/ int v;/*根据实际情况更改类型*/ }p[MAXSIZE];/*n*(n-1)/2*/ int cmp(Point a,Point b){ return a.v #include #include using namespace std; #define SIZE 101 #define MAXSIZE 10201 int n,nline;/*n 个点,nline行关系*/ int in[SIZE]; struct Point{ int x,y;/*编号从1开始*/ int v;/*根据实际情况更改类型*/ }p[MAXSIZE];/*n*(n-1)/2*/ int cmp(Point a,Point b){ return a.v #include #include #define M 501 using namespace std; int map[M][M],degree[M]; int ne;/*个数*/ void topo(){ int i,j,k; for(i=0;ine){break;}不是拓扑结构 if(i)printf(" "); printf("%d",j); degree[j]=-1; for(k=1;k<=ne;k++){ degree[k]-=map[j][k]; } } printf("\n"); } int main(){ int a,b,i,j,nline;/*nline行*/ while(scanf("%d%d",&ne,&nline)!=EOF){ memset(map,0,sizeof(map)); memset(degree,0,sizeof(degree)); while(nline--){ scanf("%d%d",&a,&b); map[a][b]=1;/*a to b*/ } for(i=1;i<=ne;i++){ for(j=1;j<=ne;j++){ if(map[i][j])degree[j]++; } } topo();/*拓扑*/ } return 0; } 1.3.最短源路径Folyd实现 #include #include #include #define M 201 using namespace std; int n,map[M][M],start,end; void folyd(){ int i,j,k; for(i=0;iv){//一个点到另一个有多条路 map[b][a]=map[a][b]=v; } } scanf("%d%d",&start,&end); folyd(); if(map[start][end]!=-1){ printf("%d\n",map[start][end]); } else printf("-1\n"); } return 0; } 1.4.关键路径实现算法 #include #include #include #define M 501 using namespace std; int map[M][M],degree[M],dp[M]; int ne;/*个数*/ int topoplus(){ int i,j,k,maxnum; for(i=0;ine){break;}不是拓扑结构 degree[j]=-1; for(k=1;k<=ne;k++){ if(map[j][k]){ if(map[j][k]+dp[j]>dp[k]){ dp[k]=map[j][k]+dp[j]; } degree[k]--; } } } for(i=0;i<=ne;i++){ if(dp[i]>maxnum){ maxnum=dp[i]; } } return maxnum; } int main(){ int a,b,v,i,j,nline;/*nline行*/ while(scanf("%d%d",&ne,&nline)!=EOF){ memset(map,0,sizeof(map)); memset(degree,0,sizeof(degree)); memset(dp,0,sizeof(dp)); while(nline--){ scanf("%d%d%d",&a,&b,&v); map[a][b]=v;/*a to b,v>0*/ } for(i=1;i<=ne;i++){ for(j=1;j<=ne;j++){ if(map[i][j])degree[j]++; } } printf("%d\n",topoplus());/*拓扑改进*/ } return 0; } 1.5.二分图最大匹配的匈牙利算法 #include #include #define N 301 using namespace std; int isuse[N]; //y中节点是否使用 int lk[N]; //记录当前与y节点相连的x的节点 int mat[N][N];//记录连接x和y的边,如果i和j之间有边则为1,否则为0 int gn,gm; //二分图中x和y中点的数目 int can(int t){ int i; for(i=1;i<=gm;i++){//下标从1开始 if(isuse[i]==0 && mat[t][i]){ isuse[i]=1; if(lk[i]==-1 || can(lk[i])){ lk[i]=t; return 1; } } } return 0; } int MaxMatch(){ int i,num=0; memset(lk,-1,sizeof(lk)); for(i=1;i<=gn;i++){ memset(isuse,0,sizeof(isuse)); if(can(i))num++; } return num; } int main(){ int t,i,j,k,tmp; scanf("%d",&t); while(t--){ scanf("%d%d",&gn,&gm); memset(mat,0,sizeof(mat));//主要得到mat这个数组 for(i=1;i<=gn;i++){ scanf("%d",&k); for(j=1;j<=k;j++){ scanf("%d",&tmp); mat[i][tmp]=1;//注意从1开始 } } if(MaxMatch()==gn){ printf("YES\n"); } else printf("NO\n"); } return 0; } /* In: 2 3 3 3 1 2 3 2 1 2 1 1 3 3 2 1 3 2 1 3 1 1 Out: YES NO */ 1.6.并查集 #include #include using namespace std; const int N=1010; int pre[N]; void Merge(int x,int y){ int i,t,rx=x,ry=y; while(pre[rx]!=-1)//搜索x的树根 rx=pre[rx]; while(pre[ry]!=-1)//搜索y的树根 ry=pre[ry]; i=x; //压缩x while(pre[i]!=-1){ t=pre[i]; pre[i]=rx; i=t; } i=y;//压缩y while(pre[i]!=-1){ t=pre[i]; pre[i]=rx; i=t; } if(ry!=rx)//合并 pre[ry]=rx; return; } int main(){ int x,y,i,ans,n,m; while(scanf("%d",&n)&&n){ scanf("%d",&m); memset(pre,-1,sizeof(pre)); for(i=0;i #include #define M 1001 using namespace std; char a[M],b[M]; int dp[M+1][M+1],lena,lenb; void init(){ int i,j; for(i=0;i<=lena;i++){ for(j=0;j<=lenb;j++){ dp[i][j]=0; } } } int cmax(int x,int y){ return x>y?x:y; } int main(){ int i,j,len; while(scanf("%s",a)!=EOF){ scanf("%s",b); init(); //下面这步很重要,否则会超时 lena=strlen(a); lenb=strlen(b); for(i=0;i #include #define M 1001 using namespace std; int a[M],dp[M]; void init(int n){ int i; for(i=0;i=0;i--){ for(j=n-1;j>i;j--){ if(a[i]dp[i]){ dp[i]=dp[j]+1; } if(dp[i]>maxlen)maxlen=dp[i]; } } } return maxlen; } void showlis(int n,int maxlen){ int i; for(i=0;i #include #include using namespace std; int type[]={150,200,350};//种类 int dp[10001]; int max(int a,int b){ return a>b?a:b; } int main(){ int t,n,i,j; scanf("%d",&t); while(t--){ scanf("%d",&n); memset(dp,0,sizeof(dp)); for(i=0;i<3;i++){ for(j=type[i];j<=n;j++){ //剩余容量为j时装的东西量最大 dp[j]=max(dp[j],dp[j-type[i]]+type[i]); } } printf("%d\n",n-dp[n]); } return 0; } 2.4.0-1背包问题 #include #include #include #define M 1002 using namespace std; int val[M],wei[M],dp[M][M]; int cmax(int a,int b){ return a>b?a:b; } int main(){ int t,n,w,i,j; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&w); for(i=1;i<=n;i++){ scanf("%d",&val[i]); } for(i=1;i<=n;i++){ scanf("%d",&wei[i]); } memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++){ for(j=0;j<=w;j++){ if(j>=wei[i]) dp[i][j]=cmax(dp[i-1][j-wei[i]]+val[i],dp[i-1][j]); else dp[i][j]=dp[i-1][j]; } } printf("%d\n",dp[n][w]); } return 0; } 2.5.母函数DP算法求组合数 2.5.1.求母函数各系数值DP #include #define M 17 #define MAX 305 using namespace std; int c1[MAX],c2[MAX],add[M+1];//add[]保存M种类 void init(){ int i; for(i=1;i<=M;i++){ add[i]=i*i; } } int solve(int n) { int i,j,k; //c1[k],c2[k]表示展开式中x^k的系数 memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); c1[0]=c2[0]=1; //使用前i种币时的情况,也即母函数展开前i个多项式的乘积 for(i=1;i<=M;i++){ //求新的多项式中的系数 for(j=0;j #include #include using namespace std; bool dp[250002]; int val[101],num[101];//对应的值和数量 int main(){ int n,i,j,sum,k; while(scanf("%d",&n)&&n>0){ sum=0; for(i=0;i=0;j--){ if(!dp[j]){ for(k=1;k<=num[i]&&k*val[i]<=j;k++){ dp[j]|=dp[j-k*val[i]]; } } } } for(i=sum/2;i>=0;i--){ if(dp[i]){ printf("%d %d\n",sum-i,i); break; } } } return 0; } /* in: 2 10 1 20 1 3 10 1 20 2 30 1 -1 out: 20 10 40 40 */ 2.6.滚动数组求回文串问题 #include #include #include #define M 5001 using namespace std; char str[M],rstr[M]; int dp[2][M];//滚动DP int cmax(int x,int y){ return x>y?x:y; } int main(){ int n,i,j,s1,s2; while(scanf("%d",&n)!=EOF){ scanf(" %s",str); //反转字符数组 for(i=0;i #include #include #define M 101 using namespace std; int n; struct Point{ int s,e; }p[M]; int cmp(Point a,Point b){ if(a.s==b.s) return a.e=start&&p[i].e<=end){ start=p[i].s; end=p[i].e; } else if(p[i].s>=end){ count++; end=p[i].e; } } return count; } int main(){ int i; while(scanf("%d",&n)&&n){ for(i=0;i using namespace std; int main(){ int t,n,i,a[100002]; int beg,end,x,y,cursum,maxsum; cin>>t; while(t--){ cin>>n; for(i=0;i>a[i]; } beg=end=1; cursum=maxsum=a[0]; x=y=1; for(i=1;imaxsum){ maxsum=cursum; beg=x; end=i+1; } } cout< #include #include using namespace std; int a[1001]; int main(){ int n,i,j,len,count,high; while(scanf("%d",&n)!=EOF){ for(i=0;i using namespace std; int main(){ int n,k,i; double sum; while(cin>>n>>k){ if(n==0&&k==0)break; if(k>n-k)k=n-k; sum=1; for(i=1;i<=k;i++){ sum*=(double)(n-k+i)/i*1.000000000001;//必需要乘 } cout<<(int)sum< #include using namespace std; const double pi=acos(-1.0);//NOTES:pi const double e= 2.71828182845904523536028747135266249775724709369995957; int main() { long long n,tt; cin>>tt; while (tt--) { cin>>n; long long ans=(long long) ((double)log10(sqrt(2*pi*n))+n*log10(n/e))+1; cout< #include using namespace std; unsigned short in[50001],ste;/*用16位的ste保存16种状态*/ unsigned short power[]= {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768}; int n,m,maxnum,i,j; void dfs(int s,int count){ if(count>maxnum)maxnum=count; for(i=s;i说明
材料未被使用*/ ste=ste|in[i]; dfs(i+1,count+1); ste=ste&(~in[i]); } } } int main(){ int tn,t; while(scanf("%d%d",&n,&m)!=EOF){ if(n==0||m==0){ printf("0\n"); continue; } for(i=0;i #include #include using namespace std; int main(){ stack s; queue q; int a[]={1,2,3,4}; /*加入*/ for(int i=0;i<4;i++){ s.push(a[i]); q.push(a[i]); } /*读取stack*/ cout<<"stack-size:"< #include #include #include using namespace std; int main(){ mapm; map::iterator p; map::reverse_iterator q; m["bd"]=2;m["ba"]=1;m["aa"]=3;m["bd"]=4; //按从小到大遍历 for(p=m.begin();p!=m.end();p++){//注意不能使用pfirst<<" "<second<first<<" "<second< #include #include #define M 26 using namespace std; int ii;//只在Tree中使用 struct Tree{ Tree* next[M]; int val; Tree(){ for(ii=0;iinext[j]==0){ p->next[j]=new Tree; } p=p->next[j]; (p->val)++; } word[0]='\0'; } while(scanf("%s",word)!=EOF){ len=strlen(word); p=root; for(i=0;inext[j]!=0){ p=p->next[j]; } else break; } if(i==len) printf("%d\n",p->val); else printf("0\n"); } return 0; } /* In: banana band bee absolute acm ba b band abc out: 2 3 1 0 */ 5.5.KMP匹配算法 #include #include #include #define M 10001 using namespace std; int s[M*100],t[M],next[M]; //得到next数组,下标均从1开始 void getnext(int m) { int i=1,j=0; next[1]=0; while(i<=m){ if(j==0||t[i]==t[j]){ ++i; ++j; next[i]=j; } else j=next[j]; } } //找不到则返回-1 int kmp(int n,int m){ int i=0,j=1; getnext(m); while(i<=n&&j<=m){ if(!j||s[i]==t[j]){ ++i; ++j; } else j=next[j]; } if(j>m) return i-m; else return -1; } int main(){ int test,m,n,i; scanf("%d",&test); while(test--){ scanf("%d %d",&n,&m); //主串s,长度为n for(i=1;i<=n;i++) scanf("%d",&s[i]); //横式串t,长度为m for(i=1;i<=m;i++) scanf("%d",&t[i]); printf("%d\n",kmp(n,m)); } return 0; } 5.6.后缀数组求最长连续公共子序列长度 #include #include #include #define M 100001 using namespace std; char message[M*2]; /*后缀数组*/ int height[M*2]; int _array[2][M*2]; int _rank[2][M*2]; int cnt[M*2]; int *array, *rank, *narray, *nrank; /*得到最长连续公共子序列长度*/ int suffix(int len1,int len2,int len){ int i,k; memset(cnt,0,1024); for(i=0;i=0;--i){ array[--cnt[message[i]]]=i; } rank[array[0]] = 0; for(i=1;i
/
本文档为【ACM 算法模板2】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索