从头开始刷ACM,真的发现过去的很多漏洞,特别越是基础的数据结构,越应该学习得精,无论是ACM竞赛,研究生考试,还是工程上,对这些基础数据结构的应用都非常多,深刻理解非常必要。不得不说最近感触还是比较多,申请阿里的校招挂了,申请的是算法工程师。然而得到的答复是第一,几乎只招研究生,本科生被Pass掉了,然后第二,问我是否有读研的打算,我说有,然后吐槽我的ACM搞得像屎一样,成绩根本无法让他满意,如果有意向,建议我能研一能拿个像样的成绩,真是2333。自己弱也怪不得别人了。
训练地址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=84416#overview
uva679
好吧,先贴一道大水题,自习室做得。
链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=620
ps:白书上代码是超时的,真是个坑
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<vector> 6 using namespace std; 7 int T; 8 int main() 9 { 10 while(cin>>T) 11 { 12 if(T==-1) 13 break; 14 while(T--) 15 { 16 int d,l,k; 17 cin>>d>>l; 18 k=1; 19 for(int i=1;i<d;i++) 20 { 21 if(l%2) 22 { 23 l=l-l/2; 24 k=k*2; 25 } 26 else 27 { 28 l=l/2; 29 k=k*2+1; 30 } 31 } 32 cout<<k<<endl; 33 } 34 35 } 36 return 0; 37 }
uva122
白书上的一道例题,第一棵二叉树,建树,bfs遍历
链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=58
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<vector> 7 #include<queue> 8 #include<cstdlib> 9 #include<cctype> 10 using namespace std; 11 const int maxn=1000; 12 char s[maxn+10]; 13 int failed=0; 14 //结点类型 15 typedef struct Tnode 16 { 17 int have_value; //是否被赋值过 18 int v; //结点值 19 struct Tnode *left,*right; 20 }Node; 21 Node* root; 22 23 Node* newnode() 24 { 25 Node* u=(Node*)malloc(sizeof(Node)); //申请动态内存 26 if(u!=NULL) //若申请成功 27 { 28 u->have_value=0; //初始化为0 29 u->left=u->right=NULL; //初始化没有左右儿子 30 } 31 return u; 32 } 33 34 void addnode(int v,char *s) 35 { 36 int n=strlen(s); 37 Node* u=root; //从根结点开始往下走 38 for(int i=0;i<n;i++) 39 if(s[i]=='L') 40 { 41 if(u->left==NULL) u->left=newnode(); //结点不存在,建立新结点 42 u=u->left; //往左走 43 } 44 else if(s[i]=='R') 45 { 46 if(u->right==NULL) u->right=newnode(); 47 u=u->right; 48 } //忽略其他情况,即最后那个多余的右括号 49 if(u->have_value) failed=1; //已经赋值,表示输入有误 50 u->v=v; 51 u->have_value=1; //做标记 52 } 53 54 void remove_tree(Node* u) 55 { 56 if(u==NULL) return; //提前判断比较稳妥 57 remove_tree(u->left); //递归释放左子树 58 remove_tree(u->right); //递归释放右子树 59 free(u); //释放u本身 60 } 61 62 int read_input() //保存读入结点 63 { 64 failed=0; 65 remove_tree(root); //释放一棵二叉树 66 root=newnode(); //创建跟结点 67 for(;;) 68 { 69 if(scanf("%s",s)!=1) return 0; //整个输入结束 70 if(!strcmp(s,"()")) break; //结束标志 71 int v; 72 sscanf(&s[1],"%d",&v); //读入结点值 73 addnode(v,strchr(s,',')+1); //查找逗号,然后插入结点 74 } 75 return 1; 76 } 77 78 int n=0,ans[maxn]; 79 int bfs() 80 { 81 int front=0,rear=1; 82 Node* q[maxn]; 83 q[0]=root; 84 while(front<rear) 85 { 86 Node* u=q[front++]; 87 if(!u->have_value) return 0; 88 ans[n++]=u->v; 89 if(u->left!=NULL) q[rear++]=u->left; 90 if(u->right!=NULL) q[rear++]=u->right; 91 } 92 return 1; 93 } 94 95 void print() 96 { 97 for(int i=0;i<n;i++) 98 { 99 if(i) printf(" "); 100 printf("%d",ans[i]); 101 } 102 printf("\n"); 103 n=0; 104 } 105 int main() 106 { 107 while(read_input()) 108 { 109 if(failed||!bfs()) cout<<"not complete"<<endl; 110 else print(); 111 } 112 return 0; 113 }
一个简单的知识点,今天复习数据结构教材的时候写的,已经前序跟中序,打印后序遍历
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<vector> 7 #include<string> 8 #include<stack> 9 using namespace std; 10 const int maxn=1000+10; 11 void build(int n,char* s1,char* s2,char* s) 12 { 13 if(n<=0) return; 14 int p=strchr(s2,s1[0])-s2; 15 build(p,s1+1,s2,s); //后序遍历左子树 16 build(n-p-1,s1+p+1,s2+p+1,s+p); //后序遍历右子树 17 s[n-1]=s1[0]; 18 } 19 int main() 20 { 21 char s1[maxn],s2[maxn],s[maxn]; 22 while(scanf("%s%s",s1,s2)==2) 23 { 24 int n=strlen(s1); 25 build(n,s1,s2,s); 26 s[n]='\0'; 27 printf("%s\n",s); 28 } 29 return 0; 30 }
uva112
这题让我学到了cin的用法,不得不感叹C++还是博大精深啊,具体请看我的下一篇文章《cin的用法》
开始想建树,后来看了别人的一些思路发现并不用建树,cin.clear()确实是新的认知,uva题目质量真心高,我一定坚持刷下去,最近进度有点慢,明天要开始一切恢复正常了,8月了,一切都开始火烧眉毛了。
下面贴一下代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<vector> 7 #include<cstdlib> 8 #include<cctype> 9 using namespace std; 10 typedef struct Tnode 11 { 12 Tnode *left,*right; 13 }node; 14 int flag; 15 node* Tree_sum(int n,int sum) 16 { 17 char ch; 18 int v; 19 cin>>ch; 20 if(!(cin>>v)==0) 21 { 22 n+=v; 23 node* root=(node*)malloc(sizeof(node)); 24 root->left=Tree_sum(n,sum); 25 root->right=Tree_sum(n,sum); 26 if(!flag&&root->left==NULL&&root->right==NULL) 27 { 28 if(sum==n) 29 flag=1; 30 } 31 cin>>ch; 32 return root; 33 } 34 else 35 { 36 cin.clear(); 37 cin>>ch; 38 return NULL; 39 } 40 } 41 int main() 42 { 43 int sum; 44 while(cin>>sum) 45 { 46 flag=0; 47 node *root=Tree_sum(0,sum); 48 if(flag) 49 cout<<"yes"<<endl; 50 else 51 cout<<"no"<<endl; 52 } 53 return 0; 54 }
二叉树一个重要知识点:(已知中序+后序,求先序)
ps:白书上是已知先序+中序,求后序,这个稍有改动,说一下,严奶奶书上这个地方代码好像有问题
下面是我的代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<vector> 7 #include<string> 8 #include<stack> 9 #include<sstream> 10 using namespace std; 11 const int maxn=1000+10; 12 int k; 13 bool read_input(int* a) 14 { 15 string line; 16 if(!getline(cin,line)) return false; 17 stringstream ss(line); 18 int x; 19 k=0; 20 while(ss>>x) a[k++]=x; 21 return k>0; 22 } 23 int i=0; 24 void build(int n,int* s1,int* s2,int* s) 25 { 26 if(n<=0) return; 27 int p=n-1; 28 s[0]=s2[p]; 29 while(s1[p]!=s2[n-1]) p--; 30 build(p,s1,s2,s+1); //先序遍历左子树 31 build(n-p-1,s1+p+1,s2+p,s+p+1); //先序遍历右子树 32 } 33 int main() 34 { 35 int pre[maxn],in[maxn],post[maxn]; 36 while(read_input(in)) 37 { 38 read_input(post); 39 build(k,in,post,pre); 40 for(int i=0;i<k;i++) 41 cout<<pre[i]<<" "; 42 cout<<endl; 43 } 44 return 0; 45 }
uva548
链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=489
不得不说这道题目写了半天,开始我以为可以先通过后序跟中序得出先序,然后向uva112那样写的,后来发现并不能这样,于是开始漫长的建树之路,之后yy出一种可以不用建树的解法,还有不得不说sstream头文件中的stringstream流输入很好用,详见刘汝佳粉书《入门经典第二版》不过最大的缺点就是速度慢
我的AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<vector> 7 #include<algorithm> 8 #include<sstream> 9 #include<cstdlib> 10 using namespace std; 11 const int maxn=10000+10; 12 int k,best_sum,best; 13 bool read_input(int* a) //输入部分 14 { 15 string line; 16 if(!getline(cin,line)) return false; 17 stringstream ss(line); 18 k=0; 19 int x; 20 while(ss>>x) a[k++]=x; 21 return k>0; 22 } 23 void dfs(int n,int sum,int* in,int* post) //深搜即可 24 { 25 if(n<=0) return; 26 int p=find(in,in+n,post[n-1])-in; 27 sum+=post[n-1]; 28 if(n==1) 29 { 30 if(sum<best_sum) 31 { 32 best_sum=sum; 33 best=post[n-1]; 34 } 35 else if(sum==best_sum) 36 best=min(best,post[n-1]); 37 return; 38 } 39 dfs(p,sum,in,post); //左子树 40 dfs(n-p-1,sum,in+p+1,post+p); //右子树 41 } 42 int main() 43 { 44 int in[maxn],post[maxn]; 45 while(read_input(in)) 46 { 47 read_input(post); 48 best_sum=best=0x3ffff; 49 dfs(k,0,in,post); 50 cout<<best<<endl; 51 } 52 return 0; 53 }
uva297
链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=104
四叉树,第一次写,不过这题比较特殊,只需要先序就可以建树,然后照着画,边画边统计
我的代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<vector> 7 #include<cstdlib> 8 #include<algorithm> 9 using namespace std; 10 const int maxn=10010; 11 char s1[maxn],s2[maxn]; 12 char *p; 13 int sum; 14 typedef struct Tnode 15 { 16 int have_value; 17 struct Tnode* child[4]; 18 }node; 19 //建立四叉树 20 node* build_tree() 21 { 22 node* root=(node*)malloc(sizeof(node)); 23 root->have_value=0; 24 if(*p=='p') 25 { 26 for(int i=0;i<4;i++) 27 { 28 ++p; 29 root->child[i]=build_tree(); 30 } 31 } 32 else 33 { 34 if(*p=='f') 35 root->have_value=1; 36 for(int i=0;i<4;i++) 37 root->child[i]=NULL; 38 } 39 return root; 40 } 41 //dfs遍历一下 42 void dfs(node* root1,node* root2,int cnt) 43 { 44 if(root1==NULL&&root2==NULL) return; 45 if(root1==NULL) 46 { 47 if(root2->have_value) 48 { 49 sum+=1024>>(2*cnt); 50 return; 51 } 52 for(int i=0;i<4;i++) 53 dfs(root1,root2->child[i],cnt+1); 54 return; 55 } 56 if(root2==NULL) 57 { 58 if(root1->have_value) 59 { 60 sum+=1024>>(2*cnt); 61 return; 62 } 63 for(int i=0;i<4;i++) 64 dfs(root1->child[i],root2,cnt+1); 65 return; 66 } 67 if(root1->have_value||root2->have_value) 68 { 69 sum+=1024>>(2*cnt); 70 return; 71 } 72 for(int i=0;i<4;i++) 73 dfs(root1->child[i],root2->child[i],cnt+1); 74 } 75 int main() 76 { 77 int T; 78 cin>>T; 79 while(T--) 80 { 81 cin>>s1>>s2; 82 p=s1; 83 node* root1=build_tree(); 84 p=s2; 85 node* root2=build_tree(); 86 sum=0; 87 dfs(root1,root2,0); 88 printf("There are %d black pixels.\n",sum); 89 } 90 }
uva712
链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=653
关键是对题目意思的理解,一个大水题,其实就是0表示向左2*n,1表示向右2*n+1,然后给出一堆查询,输出最后的序列
要换行,uva没有pe,只有WA我也是醉了,要不是看题目意思,我还找不出错误在哪儿
我的代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 using namespace std; 7 const int maxn=300; 8 string s[maxn],query[maxn]; 9 char p[maxn]; 10 int main() 11 { 12 int n,t; 13 int cas=1; 14 while(cin>>n) 15 { 16 if(n==0) 17 break; 18 for(int i=0;i<n;i++) 19 cin>>s[i]; 20 cin>>p; 21 cin>>t; 22 for(int i=0;i<t;i++) 23 cin>>query[i]; 24 int sum; 25 printf("S-Tree #%d:\n",cas); 26 for(int i=0;i<t;i++) 27 { 28 sum=1; 29 for(int j=0;j<query[i].length();j++) 30 { 31 if(query[i][j]=='0') 32 sum=sum*2; 33 else 34 sum=sum*2+1; 35 } 36 int ff=pow(2,n); 37 printf("%c",p[sum-ff]); 38 } 39 printf("\n\n"); 40 cas++; 41 } 42 return 0; 43 }
复习复习,晚上在刷一题
uva699
链接:http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=19244
题意:就是统计二叉树每一行的和为多少,给出了先序遍历。我们可以把当前位置设为p,左子树p-1,右子树p+1,然后进行递归即可
我的代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int maxn=81; 6 int sum[maxn]; 7 void build(int root,int p) 8 { 9 if(root!=-1) 10 { 11 sum[p]+=root; 12 int x,y; 13 cin>>x; 14 build(x,p-1); 15 cin>>y; 16 build(y,p+1); 17 } 18 } 19 int main() 20 { 21 int n,cas=1; 22 while(cin>>n) 23 { 24 if(n==-1) 25 break; 26 memset(sum,0,sizeof(sum)); 27 build(n,40); 28 printf("Case %d:\n",cas); 29 int k; 30 for(int i=0;i<81;i++) 31 if(sum[i]!=0) 32 { 33 k=i; 34 printf("%d",sum[i]); 35 break; 36 } 37 for(int i=k+1;i<81;i++) 38 if(sum[i]!=0) 39 printf(" %d",sum[i]); 40 printf("\n\n"); 41 cas++; 42 } 43 }
uva327
链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=263
我也不知道这题为什么放在二叉树里面,直接模拟就好了嘛,注意几种情况,a+b,a-b,a++-b,a+++b,--a,++a,然后注意处理一下空格就好了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<cctype> 7 #include<cstdlib> 8 using namespace std; 9 const int maxn=30; 10 int a[maxn],flag[maxn]; 11 int main() 12 { 13 string s; 14 while(getline(cin,s)) 15 { 16 cout<<"Expression: "<<s<<endl; 17 string ss=""; 18 for(int i=0;i<s.length();i++) 19 if(s[i]!=' ') 20 ss+=s[i]; 21 for(int i=0;i<26;i++) 22 a[i]=i+1; 23 memset(flag,0,sizeof(flag)); 24 int sum=0; 25 for(int i=0;i<ss.length();i++) 26 { 27 if(islower(ss[i])) 28 { 29 if(i==0) 30 sum+=(ss[i]-'a'+1); 31 else 32 { 33 if(ss[i-1]!=ss[i-2]) 34 { 35 if(ss[i-1]=='+') 36 sum+=ss[i]-'a'+1; 37 else if(ss[i-1]=='-') 38 sum-=ss[i]-'a'+1; 39 } 40 else 41 { 42 if(ss[i-2]=='-') 43 a[ss[i]-'a']--; 44 else if(ss[i-2]=='+') 45 a[ss[i]-'a']++; 46 if(i>3&&ss[i-3]=='-') 47 sum-=a[ss[i]-'a']; 48 else 49 sum+=a[ss[i]-'a']; 50 } 51 } 52 if(i+2<ss.length()&ss[i+1]==ss[i+2]&&ss[i+2]=='+') 53 a[ss[i]-'a']++; 54 else if(i+2<ss.length()&&ss[i+2]==ss[i+1]&&ss[i+2]=='-') 55 a[ss[i]-'a']--; 56 flag[ss[i]-'a']=1; 57 } 58 } 59 cout<<" value = "<<sum<<endl; 60 for(int i=0;i<26;i++) 61 if(flag[i]) 62 printf(" %c = %d\n",'a'+i,a[i]); 63 } 64 return 0; 65 }
uva839
链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=780
这题我参照了题解,采取递归的方式定义,因此编写一个递归进行定义就是比较自然的事情
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 int ok; 7 int dfs() 8 { 9 int wl,dl,wr,dr; 10 cin>>wl>>dl>>wr>>dr; 11 if(wl&&dl&&wr&&dr) //叶子结点 12 { 13 if(wl*dl!=wr*dr) //只要有一个不平衡全不平衡 14 { 15 ok=0; 16 return 0; 17 } 18 else return wl+wr; //返回子树的重量 19 } 20 else 21 { 22 if(!wl) wl=dfs(); //遍历左子树 23 if(!wr) wr=dfs(); //遍历右子树 24 if(wl*dl!=wr*dr) 25 { 26 ok=0; 27 return 0; 28 } 29 else 30 return wl+wr; 31 } 32 } 33 int main() 34 { 35 int T; 36 cin>>T; 37 int i=0; 38 while(T--) 39 { 40 ok=1; 41 dfs(); 42 if(i++) cout<<endl; 43 if(ok) cout<<"YES"<<endl; 44 else cout<<"NO"<<endl; 45 } 46 return 0; 47 }