【ACUMTB团队赛】第二周题解

比赛网址: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\n",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\n");
61         else printf("NO\n");
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 }

 

posted @ 2017-03-23 14:30  hymscoty  阅读(177)  评论(0编辑  收藏  举报