打起来很累,感觉不是很好,但是题意都不是特别难懂
Maratona de Programa¸c˜ao da SBC 2013
首先是A题Zero or One,签到题
给三个数(0或1),找不一样的是哪个,如果都一样就输出*
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; int main() { int a,b,c; cin>>a>>b>>c; if(a==b&&b==c) cout<<'*'<<endl; else if(a==b) cout<<'C'<<endl; else if(a==c) cout<<'B'<<endl; else if(b==c) cout<<'A'<<endl; return 0; }
D题Folding Machine感觉肯定很难,但是就是用莫名其妙,xjbg的方法水过去了
题意:给一串序列,问是否能够通过折叠转变成另一个序列
我的思路就是第二个序列的数可以用第一个序列的数表示就OK了,但是我只判断了第二个序列中的第一个数,就ac了。。
#include <cstdio> #include <iostream> #include <map> #include <algorithm> using namespace std; int cmp(int x,int y){ return x>y; } int main() { int n,m; int sum1=0,sum2=0; int a[20],b[20]; map<int,int>s; cin>>n; for(int i=0;i<n;i++){ cin>>a[i]; s[a[i]]++; sum1+=a[i]; } sort(a,a+n,cmp); cin>>m; for(int i=0;i<m;i++){ cin>>b[i]; sum2+=b[i]; } if(sum1==sum2){ for(int i=0;i<n;i++){ if(b[0]>=a[i]){ if(s[a[i]]!=0){ b[0]-=a[i]; s[b[0]-a[i]]; } } } if(b[0]==0) cout<<'S'<<endl; else cout<<'N'<<endl; } else cout<<'N'<<endl; }
E题Dangerous Dive,也是道签到题,直接上代码吧
#include <cstdio> #include <iostream> #include <queue> using namespace std; int main() { int n,m,t; int a[10005]={0}; cin>>n>>m; for(int i=0;i<m;i++){ cin>>t; a[t]=1; } if(n==m){ cout<<'*'<<endl; return 0; } for(int i=1;i<=n;i++){ if(a[i]==0) cout<<i<<' '; } return 0; }
F题Triangles,是过的人超级多的,以为是道签到题,没想到没想到啊,wa了好多次还没写出来了,还有tle,后来经过大佬的提示可以通过前缀和降低复杂度。
题意是给圆上一些点,告诉每个点之间的弧长,,然后问可以构造多少个不同的等边三角形
一开始想的比较简单,就是用一个两倍数组存,然后枚举起点,看能不能从这个点开始构造一个等边三角形,也就是能不能求和到总弧长的三分之一,然后发现tle了,后来发不需要枚举这么多点,因为像之前这么枚举的话,要重复算三倍的点,只需要枚举第一个等边三角形的两个点之间的点就OK了,发现又tle在之后的样例了,这个就很麻烦,最后在大佬的提示下,用前缀和降低复杂度,然后用map去存前缀和。。
#include <iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue> #include<map> using namespace std; map<int,int>vis; int main() { int n,m,a[100001]={0},j,temp=0,i,k,pre[100001]={0}; cin>>n; int sum=0; for(i=1;i<=n;i++) { cin>>a[i]; pre[i]=a[i]+pre[i-1]; vis[pre[i]]++; sum+=a[i]; } if(sum%3!=0) cout<<0<<endl; else { int ans=sum/3; int count=0,temp=0,cnt=0; for(i=1;i<=n;i++) { if(vis[ans+pre[i]]&&vis[ans*2+pre[i]]) cnt++; } cout<<cnt<<endl; } return 0; }
G题Lines of Containers,也是比较简单的吧
给一个n*m的矩阵,里面有1—n*m的数,问能否通过互换行或者列的方式让这个矩阵变成很舒服的矩阵,就是a【i】【j】=(i-1)*m+j
思路:就是把矩阵中1给找出来,记一下1的行和列,然后对1这一行(一列)进行排序,但是需要进行一些改变,就是在换序的时候是对这一列(行)进行换序,最后就只需要判断排序之后的这个矩阵能不能变成题目要求的这样。
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; int main() { int num[305][305]; int n,m; int a=0,b=0; int sum=0; cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>num[i][j]; if(num[i][j]==1){ a=i; b=j; } } } for(int i=1;i<=m;i++){ if(num[a][i]!=i){ int flag=0; for(int j=i+1;j<=m;j++){ if(num[a][j]==i){ if(i==1) b=j; sum++; flag=1; for(int t=1;t<=n;t++){ swap(num[t][j],num[t][i]); } } } if(flag==0){ cout<<'*'<<endl; return 0; } } } for(int i=1;i<=n;i++){ if(num[i][b]!=(i-1)*m+b){ int flag=0; for(int j=i+1;j<=n;j++){ if(num[j][b]==(i-1)*m+b){ sum++; flag=1; for(int t=1;t<=m;t++){ swap(num[j][t],num[i][t]); } } } if(flag==0){ cout<<'*'<<endl; return 0; } } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(num[i][j]!=((i-1)*m+j)){ cout<<'*'<<endl; return 0; } } } cout<<sum<<endl; return 0; }
还有就是C题,题很长,题意也比较难懂,所以在比赛中就没有去碰。
后面队友在补题的时候,说可以用dfs和拓扑排序去做。想了想贼有道理
题意就是,先给一些上下级的关系,然后构成一张关系图,然后会给你一些修改和查询,如果是修改的话就是交换两个人的位置,如果是查询的话,就是查询要查询的人的上级(包括直接和间接)中年龄最小的,如果比自己小,就输出这个年龄,如果没有即输出*
思路就是DFS,但是在修改的时候用数组进行维护,就是基本的关系网不变,但是在每次修改的时候,将位置修改的放入数组中,如果查询到这个人的时候判断一下,如果修改过,就到修改的这个人的位置上再进行dfs