AtCoder Beginner Contest 176
A.Takoyaki
题意: 一次可以做x个饼,每次花t分钟,问做n个饼花多少分钟
**题解: ** 向上取整即可,注意要用double强制转换一下
**代码: **
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 2e5 + 10;
int n ,x, t;
int main() {
cin >> n >> x >> t;
cout << (int)ceil((double)n / x) * t;
return 0;
}
B.Multiple of 9
题意: 问一个数是不是9的倍数:
**题解: ** 直接每一位相加模9即可
**代码: **
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 2e5 + 10;
int n, m, T;
int main() {
string s;
cin >> s;
LL sum = 0;
for (int i = 0; i < s.size(); ++i) {
sum += s[i] - '0';
}
if (sum % 9)
cout << "No";
else
cout << "Yes";
return 0;
}
C.Step
题意: n个人站成一排,每个人向左看,必须每个人都不高于他,否则需要修改这个人的高度,直到满足左边的人都不高于他,问需要修改的高度和最小为多少
**题解: ** 直接贪心从左到右模拟即可
**代码: **
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 2e5 + 10;
int n, m, T, a[MAXN];
int main() {
cin >> n;
LL res = 0;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
if (a[i] < a[i - 1]) {
res += abs(a[i] - a[i - 1]);
a[i] = a[i - 1];
}
}
cout << res << endl;
return 0;
}
D.Wizard in Maze
题意: 走迷宫,可以直接走,也可以通过魔法跳到当前方格周围 5 ∗ 5 5*5 5∗5的位置,"#“不可以走,”."可以走,问至少需要多少次魔法才能走到终点
**题解: ** 走迷宫先想bfs,但是怎么bfs呢,因为如果能走到那么肯定没必要用魔法,而实在是走不到了,则必须要魔法,所以我们可以采用双端队列维护,如果能直接走到,就扔到队列的前面,如果需要跳,则扔到队列的后面,然后每次都从前面取即可,这样会先把能直接走到的取到,然后再走跳数最少的位置。
**代码: **
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
typedef long long LL;
int n, m, cx, cy, tx, ty, vis[N][N];
int f[2][4] = {0, 0, 1, -1, 1, -1, 0, 0};
char a[N][N];
struct node {
int x, y;
int step;
};
void bfs() {
deque<node> q;
node start;
start.x = cx;
start.y = cy;
start.step = 0;
// vis[cx][cy] = 1;
q.push_front(start);
while (!q.empty()) {
node now = q.front();
q.pop_front();
int x = now.x;
int y = now.y;
int step = now.step;
if (vis[x][y] == 1) continue;
vis[x][y] = 1;
if (x == tx && y == ty) {
cout << step << endl;
return;
}
// 把点的情况放入队头
for (int i = 0; i < 4; i++) {
int xx = x + f[0][i];
int yy = y + f[1][i];
if (xx >= 0 && xx < n && yy >= 0 && yy < m && vis[xx][yy] == 0 &&
a[xx][yy] == '.') {
// vis[xx][yy] = 1;
node ne;
ne.x = xx, ne.y = yy, ne.step = step;
q.push_front(ne);
}
}
// 走穿墙的操作,放入队尾
for (int i = x - 2; i <= x + 2; i++) {
for (int j = y - 2; j <= y + 2; j++) {
if (i >= 0 && i < n && j >= 0 && j < m && vis[i][j] == 0 &&
a[i][j] == '.') {
// vis[i][j] = 1;
node ne;
ne.x = i, ne.y = j, ne.step = step + 1;
q.push_back(ne);
}
}
}
}
cout << -1 << endl;
return;
}
int main() {
cin >> n >> m;
cin >> cx >> cy;
cin >> tx >> ty;
cx--, cy--, tx--, ty--;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> a[i][j];
}
}
bfs();
return 0;
}
E.Bomber
题意: 给出一个 n ∗ m n*m n∗m的矩阵,其中有M个目标,现在要安放一个地雷,这个地雷可以炸掉所在行和所在列的目标,问最多可以炸掉多少目标。
1 ≤ n , m ≤ 3 × 1 0 5 1 \leq n, m \leq 3 \times 10^5 1≤n,m≤3×105
1 ≤ M ≤ min ( n × m , 3 × 1 0 5 ) 1 \leq M \leq \min\left(n\times m, 3 \times 10^5\right) 1≤M≤min(n×m,3×105)
**题解: ** 贪心的想,肯定是找到目标最多的行和列,然后判断一下这一行和这一列的交点有没有目标即可,如果有,那么答案需要减一。但是有可能有很多行或者列都是最多的,那么就需要找出他们全部的交点,看看有没有交点上没有目标的,如果有就直接输出答案,如果所有的交点上都有目标,那么直接输出答案减一即可。因为目标最多不超过3e5,所以枚举交点的数量不会超过3e5,否则一定会找到一个没有目标的交点,所以不会超时
**代码: **
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const N = 3e5 + 10;
int h, w, m;
int row[N], col[N];
int maxrow[N], mrow = 0;
int maxcol[N], mcol = 0;
set<pair<int, int>> tar;
int main() {
cin >> h >> w >> m;
int max_row = 0, max_col = 0;
for (int i = 0; i < m; i++) {
int x, y;
cin >> x >> y;
tar.insert({x, y});
row[x]++;
col[y]++;
max_row = max(max_row, row[x]);
max_col = max(max_col, col[y]);
}
for (int i = 1; i <= h; i++) {
if (row[i] == max_row) maxrow[mrow++] = i;
}
for (int i = 1; i <= w; i++) {
if (col[i] == max_col) maxcol[mcol++] = i;
}
for (int i = 0; i < mrow; i++) {
for (int j = 0; j < mcol; j++) {
if (tar.count({maxrow[i], maxcol[j]}) == 0) {
cout << max_row + max_col << endl;
return 0;
}
}
}
cout << max(0, max_row + max_col - 1) << endl;
return 0;
}