Atcoder ABC351 A-E 题解

A:

打卡题

题目描述

 一中队和二中队正在进行一场棒球比赛,一中队是第一棒。  

目前,比赛已进行到第九局上半,第九局下半即将开始。

一中队在 第i局 (1 <= i <= 9) 上半场得到了 Ai 分,二中队在 第j局 (1 <= j <= 8) 下半场得到了 Bj 分。  

第九局上半结束时,一中队的得分不低于二中队的得分。  

求二中队在第九局下半至少需要得到多少分才能赢得比赛。

在这里,如果比赛在第九局下半结束时打成平手,结果就是平局。因此,二中队要想获胜,就必须在第九局下半结束时比一中队严格多得一分。  

一中队在任何时候的得分都是截至该点的上半局总得分,而二中队的得分则是下半局的总得分。

输入

A1 A2 A3 A4 A5 A6 A7 A8 A9

B1 B2 B3 B4 B5 B6 B7 B8

输出

打印二中队在第九局下半段至少需要得到多少分才能获胜。

样例输入1

0 1 0 1 2 2 0 0 1
1 1 0 0 0 0 1 0

样例输出1

5

样例输入2

0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

样例输出2

1

#include<iostream>
using namespace std;
int main(){
    int middle_school_1=0;
    int middle_school_2=0;
    for(int i=0;i<9;i++){
        int a;
        cin>>a;
        middle_school_1+=a;
    }
    for(int i=0;i<8;i++){
        int x;
        cin>>x;
        middle_school_2+=x;
    }
    cout<<middle_school_1-middle_school_2+1;
    return 0;
}

B:

简单题

题目描述

 给你两个网格,每个网格都有 N 行和 N 列,分别称为网格 A 和网格 B 。  

网格中的每个单元格都包含一个小写英文字母。  

网格 A 的 i 行和 j 列的字符是 𝐴𝑖,𝑗 。  

网格 B 的 i 行和 j 列的字符是 𝐵𝑖,𝑗 。

这两个网格正好有一个单元格不同。也就是说,存在一对 (i, j) 不大于 N 的正整数,使得 𝐴𝑖,𝑗 != 𝐵𝑖,𝑗 。

求这个 (i, j) 

输入

N

𝐴1,1 𝐴1,2... 𝐴1,𝑁

𝐴2,1 𝐴2,2... 𝐴2,𝑁

......

𝐴𝑁,1 𝐴𝑁,2... 𝐴𝑁,𝑁

𝐵1,1 𝐵1,2... 𝐵1,𝑁

𝐵2,1 𝐵2,2... 𝐵2,𝑁

......

𝐵𝑁,1 𝐵𝑁,2... 𝐵𝑁,𝑁

输出

设 (i, j) 是一对不大于 N 的正整数,且  𝐴𝑖,𝑗 != 𝐵𝑖,𝑗  .按以下格式打印 (i, j) :

i j

样例输入1

3
abc
def
ghi
abc
bef
ghi

样例输出1

2 1

样例输入2

1
f
q

样例输出2

1 1

样例输入3

10
eixfumagit
vtophbepfe
pxbfgsqcug
ugpugtsxzq
bvfhxyehfk
uqyfwtmglr
jaitenfqiq
acwvufpfvv
jhaddglpva
aacxsyqvoj
eixfumagit
vtophbepfe
pxbfgsqcug
ugpugtsxzq
bvfhxyehok
uqyfwtmglr
jaitenfqiq
acwvufpfvv
jhaddglpva
aacxsyqvoj

样例输出3

5 9

思路:直接暴力枚举

#include<bits/stdc++.h>
using namespace std;
char s1[105][105],s2[105][105];
int main() {
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>s1[i][j];
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=n;j++){
        	cin>>s2[i][j];
        	if(s1[i][j]!=s2[i][j]){
            	cout<<i<<" "<<j;
            	return 0;
        	}
    	}
    }
    return 0;
}

C:

简单题

题目描述

你有一个空序列和 N 个球。球 (1  <= i  <= N) 的大小是 2^{Ai} 。

你将进行 N 次运算。  

在第i次操作中,你将把第i个球添加到序列的右端,然后重复下面的步骤:

1.  如果序列中只有一个或更少的球,则结束操作。

2.  如果序列中最右边的球和第二个最右边的球大小不同,结束操作。

3.  如果序列中最右边的球和最右边的第二个球的大小相同,则移除这两个球,并在序列的右端添加一个新球,其大小等于移除的两个球的大小之和。然后回到步骤 1,重复上述过程。

计算 N 操作后序列中剩余的球数。

输入

N

A1 A2 ... An

输出

打印 N 操作后序列中的球数。

样例输入1

7
2 1 1 3 5 3 3

样例输出1

3

样例输入2

5
0 0 0 1 2

样例输出2

4

思路:小球的操作符合栈的特性(stack),用栈存储小球数据

#include<bits/stdc++.h>
using namespace std;
stack<int> s;//栈
int n,x;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>x;
        s.push(x);
        while(s.size()>=2){
            int a=s.top();
            s.pop();
            int b=s.top();
            s.pop();
            if(a!=b){
                s.push(b);
                s.push(a);
                break;
            }
            else s.push(a+1);
        }
    }
    cout<<s.size();
    return 0;
}

D:

搜索题

题目描述

有一个行数为 H ,列数为 W 的网格。有些单元格(可能为零)包含磁铁。  

网格的状态由长度为 W 的 H 个字符串 S1, S2, ..., SH 表示。如果 Si 的 第j个 字符是 "#",则表示在从上往下的第i行和从左往右的第j列的单元格中有磁铁;如果是".",则表示单元格是空的。

身穿铁甲的小奇可以在网格中做如下移动:

  •  如果与当前单元格垂直或水平相邻的任何一个单元格中含有磁铁,他就不能移动。
  •  否则,他可以移动到任何一个垂直或水平相邻的单元格。  

    但是,他不能离开网格。

对于每个没有磁铁的单元格,将其自由度定义为他从该单元格重复移动所能到达的单元格数。求网格中所有没有磁铁的单元格的最大自由度。

这里,在自由度的定义中,"他可以通过重复移动到达的单元格 "指的是从初始单元格通过一定的移动序列(可能是零移动)可以到达的单元格。不一定要有一个移动序列能从初始单元格开始访问所有这些可到达的单元格。具体来说,每个单元格本身(没有磁铁)总是包含在从该单元格可到达的单元格中。

输入

H W

S1

S2

...
𝑆𝐻

输出

打印所有磁铁的最大自由度。

样例输入1

3 5
.#...
.....
.#..#

样例输出1

9

样例输入2

3 3
..#
#..
..#

样例输出2

1

思路:我们先看样例1,让 (i,j) 表示从上往下第 i 行,从左往上第 j 列的单元格。如果小奇开始于 (2,3) ,那么可能的移动包括:

 (2,3)  ->  (2,4)  ->  (1,4)  ->  (1,5)  ->  (2,5)

 (2,3)  ->  (2,4)  ->  (3,4)

 (2,3)  ->  (2,2)

 (2,3)  ->  (1,3)

 (2,3)  ->  (3,3)

 因此,包括他经过的单元格在内,他至少可以从 (2,3) 到达九个单元格。  

实际上,没有其他单元格可以到达,因此 (2,3) 的自由度为 9 。

这是所有没有磁铁的单元格的最大自由度,因此打印 9 。

稍微分析一下,可以用BFS来解

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
int ans = 1, cnt = 5;
int h, w; 
int vis[1010][1010];
bool check(int x, int y) {
	bool isi = true;
	for (int i = 0; i < 4; i ++ ) {
		int u = x + dx[i], v = y + dy[i];
		if (vis[u][v] == 2) isi = false;
	}
	return isi;
}
void bfs(int x, int y) {
	int res = 1;
	queue<PII> q;
	q.push({x, y});
    vis[x][y] = 1;
    while (!q.empty()) {  
        pair<int, int> t = q.front(); q.pop();  
        int x1 = t.first, y1 = t.second;  
          
        for (int i = 0; i < 4; i++) {  
            int x2 = x1 + dx[i], y2 = y1 + dy[i];  
            if (x2 < 1 || x2 > h || y2 < 1 || y2 > w) continue;  
            if (vis[x2][y2] == 1 || vis[x2][y2] == 2) continue;  
              
            if (!check(x2, y2)) {  
                if (vis[x2][y2] == cnt) continue;  
                vis[x2][y2] = cnt;  
                res++;  
            }  
            else {  
                res++;  
                vis[x2][y2] = 1;  
                q.push(make_pair(x2, y2));  
            }  
        }  
    }  
    ans = max(ans, res);
}
	

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); 
    cout.tie(0);
	cin >> h >> w;
	for (int i = 1; i <= h; i ++ ) {
		for (int j = 1; j <= w; j ++ ) {
			char c; 
            cin >> c;
			if (c == '#') vis[i][j] = 2;
		}
	}
	for (int i = 1; i <= h; i ++ ) {
		for (int j = 1; j <= w; j ++ ) {
			if (vis[i][j] == 0 && check(i, j)) {
				bfs(i, j);
				cnt += 1;
			} 
		}
	}
	cout << ans << '\n';
	return 0;
}

E:

分析题

题目描述

在坐标平面上有 N 个点 P1, P2, ..., PN ,其中点 Pi 的坐标为 (Xi, Yi) 。  

两点 A 与 B 之间的距离 dist(A, B) 定义如下:

  •  一只兔子最初位于点 A 。  
  • 位置为 (x, y) 的兔子可以跳跃到 (x+1, y+1) 、 (x+1, y-1) 、 (x-1, y+1) 或 (x-1, y-1) 。  
  • dist(A, B) 被定义为从 A 点到 B 点所需的最少跳跃次数。  
  • 如果经过任意次数的跳跃都无法从点 A 到达点 B ,则设为 dist(A, B) = 0 。

计算总和∑𝑖=1𝑁-1∑𝑗=𝑖+1𝑁dist(Pi, Pj) 。

输入

N

X1 Y1

X2 Y2

...

Xn Yn

输出

将∑𝑖=1𝑁-1∑𝑗=𝑖+1𝑁dist(Pi, Pj)的值打印为整数

样例输入1

3
0 0
1 3
5 6

样例输出1

3

样例输入2

5
0 5
1 7
2 9
3 8
4 6

样例输出2

11

思路:先看样例1,

P1 、 P2 和 P3 的坐标分别为 (0,0) 、 (1,3) 和 (5,6) 。  

兔子可以通过 (0,0)  ->  (1,1)  ->  (0,2)  ->  (1,3) 在三次跳跃中从 P1 到达 P2 ,但无法在两次或更少的跳跃中到达,所以是 dist(P1, P2) = 3 。  

兔子无法从 P1 到达 P3 ,也无法从 P2 到达 P3 ,因此是 dist(P1, P3) = dist(P2, P3) = 0 。

因此,答案是∑𝑖=12∑𝑗=𝑖+13dist(Pi, Pj)=dist(P1, P2)+dist(P1, P3)+dist(P2, P3)=3+0+0=3 。

我们可以看出,

兔子的移动是对角移动,不太方便进行操作。我们可以把坐标轴旋转45°,再放大两倍

所以,兔子可以从( x , y ) (x,y)(x,y)跳跃到( x + 2 , y ) , ( x , y + 2 ) , ( x , y − 2 ) (x+2,y), (x,y+2) , (x,y−2)(x+2,y),(x,y+2),(x,y−2)和( x − 2 , y ) (x−2,y)(x−2,y)

这道题是 曼哈顿距离 问题

出租车几何或曼哈顿距离(Manhattan Distance)是由十九世纪赫尔曼·闵可夫斯基所创词汇 ,是种使用在几何度量空间的几何学用语,用以标明两个点在标准坐标系上的绝对轴距总和。

图1中红线代表曼哈顿距离,绿色代表欧氏距离,也就是直线距离,而蓝色和黄色代表等价的曼哈顿距离。曼哈顿距离——两点在南北方向上的距离加上在东西方向上的距离,即d(i,j)=|xi-xj|+|yi-yj|。对于一个具有正南正北、正东正西方向规则布局的城镇街道,从一点到达另一点的距离正是在南北方向上旅行的距离加上在东西方向上旅行的距离,因此,曼哈顿距离又称为出租车距离。曼哈顿距离不是距离不变量,当坐标轴变动时,点间的距离就会不同。曼哈顿距离示意图在早期的计算机图形学中,屏幕是由像素构成,是整数,点的坐标也一般是整数,原因是浮点运算很昂贵,很慢而且有误差,如果直接使用AB的欧氏距离(欧几里德距离:在二维和三维空间中的欧氏距离的就是两点之间的距离),则必须要进行浮点运算,如果使用AC和CB,则只要计算加减法即可,这就大大提高了运算速度,而且不管累计运算多少次,都不会有误差。

(图一)

最后最后一定要把结果除以2(我们放大了两倍)

#include<bits/stdc++.h>
using namespace std;
long long n,ans=0;
vector<long long>x[2][2],y[2][2]; 
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        int x1,y1;
        cin>>x1>>y1;
        x[(x1+y1)%2][abs(x1-y1)%2].push_back(x1+y1);
        y[(x1+y1)%2][abs(x1-y1)%2].push_back(x1-y1);
    }
	for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            int nx=x[i][j].size();
            int ny=y[i][j].size();
            if(nx==0) continue;
			sort(x[i][j].begin(),x[i][j].end());
            sort(y[i][j].begin(),y[i][j].end());
			long long prex=x[i][j][0],prey=y[i][j][0];
            for(int k=1;k<nx;k++){
                ans+=k*x[i][j][k]-prex;
                prex+=x[i][j][k];
            }
            for(int k=1;k<ny;k++){
                ans+=k*y[i][j][k]-prey;
                prey+=y[i][j][k];
            }
        }
    }
	cout<<ans/2;
    return 0;
}

本期题解到此结束,下期不见不散

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值