比赛网址:https://vjudge.net/contest/154804
A题:
思路:水题……
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 int a[100]; 5 int main() 6 { 7 int N,p[4]={0,0,0,0}; 8 cin>>N; 9 for(int i=1;i<=N;i++) 10 { 11 int x; 12 cin>>x; 13 p[i%3]+=x; 14 } 15 int maxn=max(p[0],max(p[1],p[2])); 16 if(maxn==p[0]) 17 cout<<"back"<<endl; 18 else if(maxn==p[1]) 19 cout<<"chest"; 20 else 21 cout<<"biceps"<<endl; 22 return 0; 23 }
B题:
题意:给你一个a串和b串,问a串中几个连续的与b差值相等的子串。
思路:KMP,由于是连续的串,所以将a和b串处理成相邻元素的差值的串,再进行匹配。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 6 using namespace std; 7 8 const int maxn=2e5+10; 9 10 int next[maxn]; 11 12 int a[maxn],b[maxn]; 13 14 int n,w; 15 16 inline int read(){ 17 int x=0,f=1;char ch=getchar(); 18 while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} 19 while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 23 void kmp_pre(){ 24 int i,j;j=next[0]=-1; 25 i=0; 26 while(i<w-1){//注意是w-1 27 while(j!=-1&&b[i]!=b[j]) j=next[j]; 28 next[++i]=++j; 29 } 30 } 31 32 int main(){ 33 n=read();w=read(); 34 for(int i=0;i<n;i++) a[i]=read(); 35 for(int i=0;i<w;i++) b[i]=read(); 36 for(int i=0;i<n-1;i++) a[i]=a[i+1]-a[i];//差值处理 37 for(int i=0;i<w-1;i++) b[i]=b[i+1]-b[i];//差值处理 38 a[n]=0;b[w]=0; 39 kmp_pre(); 40 int i=0,j=0,cnt=0; 41 while(i<n){ 42 while(j!=-1&&a[i]!=b[j]) j=next[j]; 43 ++i;++j; 44 if(j>=w-1){//注意是w-1 45 cnt++; 46 j=next[j]; 47 } 48 } 49 printf("%d ",cnt); 50 return 0; 51 }
C题:
题意:
给一个3*n的网格,格子上有k个火车,人在s点(网格最左端)。
人在每个时刻必须向右走一格,走后可以选择向上,下走一格或者不动,火车每个时刻固定向左走两格,人先走。
人不能撞到火车,询问人是否能走到网格最右端。
思路:
火车不动,人每次走时判断位置是否可行(即(x,y),(x,y+1),(x,y+2)是否有火车,相当于判断下一时刻会不会被火车撞到),每次走2步(代替火车的运动)。
1 #include <iostream> 2 #include <queue> 3 #include <cstring> 4 #include <cstdio> 5 6 using namespace std; 7 const int maxn=105; 8 9 struct node{ 10 int x,y; 11 }; 12 13 char mp[3][maxn]; 14 bool used[3][maxn]; 15 int dir[3]={0,1,-1}; 16 17 int n,k; 18 19 bool bfs(int sx,int sy){ 20 queue<node> q; 21 q.push((node){sx,sy}); 22 while(!q.empty()){ 23 node now=q.front(); 24 q.pop(); 25 if(now.y>=n-1) return true;//到达最右端 26 if(!used[now.x][++now.y]){//必须要向左走一格 27 for(int i=0;i<3;i++){ 28 int dx=now.x+dir[i]; 29 int dy=now.y; 30 if(dx>=0&&dx<3&&!used[dx][dy]&&!used[dx][dy+1]&&!used[dx][dy+2]){//判断位置是否合法 31 used[dx][dy+2]=1;//每次走两步 32 q.push((node){dx,dy+2}); 33 } 34 } 35 } 36 } 37 return false; 38 } 39 40 int main(){ 41 int T; 42 scanf("%d",&T); 43 while(T--){ 44 scanf("%d %d",&n,&k); 45 memset(used,0,sizeof(used)); 46 for(int i=0;i<3;i++){ 47 scanf("%s",mp[i]); 48 } 49 int sx,sy; 50 for(int i=0;i<3;i++){ 51 for(int j=0;j<n;j++){ 52 if(mp[i][j]=='s'){ 53 sx=i;sy=j; 54 } 55 else{ 56 if(isalpha(mp[i][j])) used[i][j]=1; 57 } 58 } 59 } 60 if(bfs(sx,sy)) printf("YES "); 61 else printf("NO "); 62 } 63 return 0; 64 }
D题:
题意:
给定n,有一个n*n的棋盘,白皇后和黑皇后在棋盘的左右上角((1,1),(1,n)),其他地方均布满绿色棋子。皇后每次可以横向纵向斜向移动,但必须要吃到一个绿色棋子,吃到后停在该位置。
白皇后先手,当自己被对方皇后吃掉或者该次移动无法吃到绿色棋子时输掉游戏,反之则赢得游戏。
每个皇后都采取当前最优策略,问你最后的赢家,如果是白皇后,还需输出她第一次移动到的坐标。
思路:
这道题……证明起来感觉太复杂,比赛时猜了一下结论,类似于划地盘一样,两个皇后刚开始的最优策略都是尽可能的靠近对方,使自己的地盘尽可能大,由于白皇后先手所以当n-2为偶数时胜利,奇数时失败。由于给定了坐标,所以第一步肯定是(1,2)。
1 #include <iostream> 2 3 using namespace std; 4 5 int main(){ 6 int n; 7 cin>>n; 8 if(n==2){ 9 cout<<"white"<<endl; 10 cout<<1<<" "<<2<<endl; 11 } 12 else if((n-2)%2==0){ 13 cout<<"white"<<endl; 14 cout<<1<<" "<<2<<endl; 15 } 16 else cout<<"black"<<endl; 17 return 0; 18 }
E题:
题意:一个塔的层数L需要一定数量的砖块搭成,现在给你砖块数量n,问你能搭最高几层?
思路:就是个数列,一定数量的意思是数列的通项公式的值……比赛上不怎么想推公式,打了个表就交上去了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 #include <set> 6 #include <algorithm> 7 #include <vector> 8 9 using namespace std; 10 11 typedef long long ll; 12 13 const ll maxn=1e12+10; 14 15 vector<ll> v; 16 17 void pre(){ 18 ll cou=3; 19 for(ll i=cou;i<maxn;i+=(cou+=2)){ 20 v.push_back(i); 21 } 22 } 23 24 int main(){ 25 pre(); 26 int T;int cou=0; 27 cin>>T; 28 ll n; 29 while(T--){ 30 cin>>n; 31 cout<<"Case "<<++cou<<": "<<upper_bound(v.begin(),v.end(),n)-v.begin()<<endl; 32 } 33 return 0; 34 }