Atcoder Beginner Contest 460
C - Sushi
问题核心
一个长为 \(N\) 的序列和一个长为 \(M\) 的序列,如果 \(N_i <= 2M_j\),\(N_i\) 和 \(M_j\) 就能匹配,求最大匹配数。
思路
都从小到大排序,因为如果 \(M_j\) 与 \(N_i\) 匹配,对于所有 \(N_p(p > i)\) 都能和 \(M_j\) 匹配,所有贪心策略就是尽可能让 \(M_j\) 匹配跟小的 \(N_i\)
细节见这里。
反思总结
1.有两个集合,一个集合的资源能“覆盖”另一个集合的元素,且覆盖能力随资源大小单调递增,希望最大化配对数量。这种问题要想到排序 + 双指针贪心。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<int> sh(n);
vector<int> ne(m);
for (int i = 0; i < n; i++) cin >> sh[i];
for (int i = 0; i < m; i++) cin >> ne[i];
sort(sh.begin(), sh.end());
sort(ne.begin(), ne.end());
int ans = 0;
int i = 0, j = 0;
while (i < n && j < m){
if(ne[j] <= sh[i] * 2){
ans++;
i++;
j++;
}else{
i++;
}
}
cout << ans;
}
D - Repeatedly Repainting
问题核心
网格中有黑白格,每次变化,黑变白,而周围8格有黑格的白格才会变黑,求 \(10^{100}\) 变化后的网格
思路
注意到第一次变化由于可能有大片相邻黑格所以是特别的,直接模拟。之后可以通过多源BFS来搜索每个白格到黑格最近的距离,最后根据这个距离的奇偶性和已经操作次数的奇偶性来判断最后的结果
总结反思
一开始想着纯模拟知道所以白格旁边都有黑格停止,没考虑他第一次的变化是特殊的,经典的反例就是出现大片黑和一条白的情况会直接结束,答案是错的。
- 求所有一类点到一类点的最短距离可以考虑多源BFS
- 很多次变化的题目,往往可以先模拟几次,过了特殊的变化出现边界效应,就可以通过规律来做了,也有先通过循环节,最后暴力模拟求解答案的题。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int h, w;
cin >> h >> w;
vector<vector<int>> grid(h, vector<int>(w));
queue<pair<int, int>> q;
int c1 = 0;
for (int i = 0; i < h; i++){
for (int j = 0; j < w; j++){
char x; cin >> x;
if(x == '#'){
grid[i][j] = 0;
c1++;
}else
grid[i][j] = -1;
}
}
const int d[8][2] = {{-1, 0}, {-1, 1}, {-1, -1}, {0, 1}, {0, -1}, {1, 1}, {1, 0}, {1, -1}};
vector<pair<int, int>> re;
for (int i = 0; i < h; i++){
for (int j = 0; j < w; j++){
if(grid[i][j] == 0)
re.push_back({i, j});
else
for (int k = 0; k < 8; k++){
int r = i + d[k][0], c = j + d[k][1];
if(r >= 0 && r < h && c >= 0 && c < w && grid[r][c] == 0){
re.push_back({i, j});
break;
}
}
}
}
for(auto& [i, j] : re){
if(grid[i][j] == 0)
grid[i][j] = -1;
else{
grid[i][j] = 0;
q.push({i, j});
}
}
int cnt = 0;
while(!q.empty()){
cnt++;
int sz = q.size();
for (int _ = 0; _ < sz; _++){
auto [i, j] = q.front(); q.pop();
for (int k = 0; k < 8; k++){
int r = i + d[k][0], c = j + d[k][1];
if(r >= 0 && r < h && c >= 0 && c < w && grid[r][c] == -1){
grid[r][c] = cnt;
q.push({r, c});
}
}
}
}
for (int i = 0; i < h; i++){
for (int j = 0; j < w; j++){
if((grid[i][j] & 1) && grid[i][j] != -1)
cout << '#';
else
cout << '.';
}
cout << "\n";
}
}

浙公网安备 33010602011771号