RC-u1 早鸟价
【题目大意】:给出一年内的某个日期和付款金额,判断付款金额是否满足对应要求
【解题思路】:按照题意分日期模拟即可
【核心代码】:
void solve(){
int m, d, c;
std::cin >> m >> d >> c;
if(m > 7){
std::cout << "Too late!\n";
}
else if(m == 7){
if(d > 11)std::cout << "Too late!\n";
else{
if(c > 2000)std::cout << "^_^\n";
else if(c == 2000)std::cout << "Ok!\n";
else std::cout << "Need more!\n";
}
}
else if(m == 6){
if(d > 20){
if(c > 2000)std::cout << "^_^\n";
else if(c == 2000)std::cout << "Ok!\n";
else std::cout << "Need more!\n";
}
else{
if(c > 1800)std::cout << "^_^\n";
else if(c == 1800)std::cout << "Ok!\n";
else std::cout << "Need more!\n";
}
}
else{
if(c > 1800)std::cout << "^_^\n";
else if(c == 1800)std::cout << "Ok!\n";
else std::cout << "Need more!\n";
}
}
RC-u2 谁进线下了?III
【题目大意】:给出一个队伍的 nnn 场比赛排名和得分,判断这个队伍的 nnn 场是否有 50%50\%50% 及以上的场次排名第一,以及 nnn 场比赛总分是否超过第二名 505050 分及以上
【解题思路】:按照题意模拟,需要注意 nnn 为奇数时直接判断 cnt >= n / 2 有误(如 n = 9,n / 2 == 4,但 444 场并没有达到 50%50\%50%),正确做法是对 nnn 除以 222 上取整 :cnt >= (n + 1) / 2
【核心代码】:
void solve(){
int n, s;
std::cin >> n >> s;
int cnt = 0, sum = 0;
for(int i = 0; i < n; i++){
int r, c;
std::cin >> r >> c;
if(r == 1)cnt++;
sum += c;
}
if(cnt >= (n + 1) / 2)std::cout << 1 << ' ';
else std::cout << 0 << ' ';
if(sum - s >= 50)std::cout << 1 << '\n';
else std::cout << 0 << '\n';
}
RC-u3 点格棋
【题目大意】:给出一个下点格棋的规则,判断每一步下棋是否满足规则,以及求出最终获胜者及其得分(成功连成一个小方格即可得分)
【解题思路】:需要注意的点有很多,主要有以下点:
- 第一轮是否为小 A 先手
- 两点所连成的线是否已经在之前连过
- 是否为垂直或水平,且长度为 111 的线
- 所连的线是否超出棋盘
- 去掉不合法的步骤后,是否满足小 A 和小 B 依次下棋
- 成功连成一个小方格后可以额外在进行一个回合
下面提供的代码用mp记录某条线是否已经被连接过,用g[x][y]表示格点g[x - 1][y - 1]、g[x][y - 1]、g[x - 1][y]、g[x][y]是否已成功被连接。成功被连接后赋值为 −1-1−1
【核心代码】:
void solve(){
int n, m, s;
std::cin >> n >> m >> s;
std::vector<std::vector<int>>g(n + 10, std::vector<int>(m + 10));
std::map<std::pair<std::pair<int, int>, std::pair<int, int>>, int>mp;
std::vector<int>ans;
int sum[2] = {0, 0};
auto check = [&](int x, int y, int t)->int{
int f = 0;
if(x <= n && x - 1 >= 1 && y - 1 >= 1 && y <= m){
if(mp[{{x - 1, y - 1}, {x - 1, y}}] == 1 && mp[{{x - 1, y - 1}, {x, y - 1}}] == 1 &&
mp[{{x, y}, {x - 1, y}}] == 1 && mp[{{x, y}, {x , y - 1}}] == 1 && g[x][y] != -1){
sum[t]++;
f = 1;
g[x][y] = -1;
}
}
if(x <= n && x - 1 >= 1 && y >= 1 && y + 1<= m){
if(mp[{{x - 1, y}, {x - 1, y + 1}}] == 1 && mp[{{x - 1, y}, {x, y}}] == 1 &&
mp[{{x, y + 1}, {x - 1, y + 1}}] == 1 && mp[{{x, y + 1}, {x , y}}] == 1 && g[x][y + 1] != -1){
sum[t]++;
f = 1;
g[x][y + 1] = -1;
}
}
if(x + 1 <= n && x >= 1 && y - 1 >= 1 && y <= m){
if(mp[{{x, y - 1}, {x, y}}] == 1 && mp[{{x, y - 1}, {x + 1, y - 1}}] == 1 &&
mp[{{x + 1, y}, {x, y}}] == 1 && mp[{{x + 1, y}, {x + 1 , y - 1}}] == 1 && g[x + 1][y] != -1){
sum[t]++;
f = 1;
g[x + 1][y] = -1;
}
}
if(x + 1 <= n && x >= 1 && y >= 1 && y + 1 <= m){
if(mp[{{x, y}, {x, y + 1}}] == 1 && mp[{{x, y}, {x + 1, y}}] == 1 &&
mp[{{x + 1, y + 1}, {x + 1, y}}] == 1 && mp[{{x + 1, y + 1}, {x, y + 1}}] == 1 && g[x + 1][y + 1] != -1){
sum[t]++;
f = 1;
g[x + 1][y + 1] = -1;
}
}
return f;
};
int k = 0;
for(int i = 0; i < s; i++){
int t, sx, sy, ex, ey;
std::cin >> t >> sx >> sy >> ex >> ey;
if(k != t){
ans.push_back(i);
continue;
}
if(mp[{{sx, sy}, {ex, ey}}] == 1){
ans.push_back(i);
continue;
}
if(sx != ex && sy != ey){
ans.push_back(i);
continue;
}
if(sx == ex && sy == ey){
ans.push_back(i);
continue;
}
if(std::abs(sx - ex) >= 2 || std::abs(sy - ey) >= 2){
ans.push_back(i);
continue;
}
if(sx < 0 || sx > n || sy < 0 || sy > m|| ex < 0 || ex > n || ey < 0 || ey > m){
ans.push_back(i);
continue;
}
mp[{{sx, sy}, {ex, ey}}] = 1;
mp[{{ex, ey}, {sx, sy}}] = 1;
k ^= 1;
int f = 0;
f += check(sx, sy, t);
f += check(ex, ey, t);
if(f)k ^= 1;
}
if(ans.size()){
std::cout << ans[0] + 1;
for(int i = 1; i < ans.size(); i++)std::cout << ' ' << ans[i] + 1;
}
else std::cout << -1;
std::cout << '\n';
if(sum[0] > sum[1])
std::cout << 0 << ' ' << sum[0];
else
std::cout << 1 << ' ' << sum[1];
}
RC-u4 Tree Tree 的
【题目大意】:在无向图找出满足以下两个条件的无向图最大子图和次大子图(次大子图严格小于最大子图):
1.子图 G′ 原来连通,删去任一节点后仍然不连通
2.子图 G′ 在删去任一节点后能够仅构成一棵树。
【解题思路】:
- 当图中存在环时,题目可以转为求出最大子环和次大子环环上的节点个数(一个环满足节点数=边数,任意删去一个节点后依然连通且构成一棵 n−1n - 1n−1 个节点 m−2m - 2m−2 条边的树);
- 当图中不存在环或仅存在一种环(即不存在次大环)时,则不能按照上面找环的办法来求解(注意到环一定满足题目的两个条件,但满足题目两个条件的不一定是环)。此时如果图中存在一条边,可以证明这条边所连接的两个点构成的子图也满足题目的两个条件(容易证明更长的链或者其他非环子图都不满足题意);
- 如果图中不存在任何边(题目中数据范围为 n≥1, m≥0n \ge 1,\,\ m \ge 0n≥1, m≥0),一个节点构成的图也满足题目条件(删除这个节点后图中不存在节点,即空树)
【核心代码】:
void solve(){
int n, m;
std::cin >> n >> m;
std::vector<std::vector<int>> g(n);
for (int i = 0; i < m; i++) {
int x, y;
std::cin >> x >> y;
x -= 1;
y -= 1;
g[x].push_back(y);
g[y].push_back(x);
}
int res1 = 1, res2 = 0;
std::vector<int> f(n, 0);
auto dfs = [&](auto &self, int u, int v, int d, int root)->void{
for(auto x : g[v]){
if(f[x])continue;
if(x == root){
if(d > res1){
res2 = res1;
res1 = d;
}
else if(d > res2 && d != res1){
res2 = d;
}
}
f[x] = 1;
self(self, v, x, d + 1, root);
f[x] = 0;
}
};
for(int i = 0; i < n; i++){
dfs(dfs, -1, i, 1, i);
}
std::cout << res1 << ' ' << res2 << '\n';
}
【补充】:树是 n(n≥0)n(n \ge 0)n(n≥0)个结点的有限集 。当 n=0n = 0n=0 时,称为空树。在任意一棵非空树中应满足:
- 有且仅有一个特定的称为根的结点;
- 当 n>1n > 1n>1 时,其余结点可分为 m(m>0)m(m > 0)m(m>0) 个互不相交的有限集 TTT,其中每一个集合本身又是一棵树,并且称为根的子树。
RC-u5 游戏设计师
【题目大意】:将一个1×1×21\times 1\times 21×1×2 的长方体通过翻滚(翻滚一次记为一步)从起点移动到给定位置,对给定 qqq 个初始起点状态(包括初始坐标和横卧或者竖立状态)求出到达终点的最少步数。如果无法到达输出 −1-1−1
平面上有三种格子:坚实格、易碎格和空格。
坚实格:可以作为横卧时的两个支撑格之一,或者作为长方块竖立时唯一的支撑格。
易碎格:可以作为横卧时的两个支撑格之一,不能作为长方块竖立时唯一的支撑格。
空 格:长方块的任何部分都不能位于空格之上。
【解题思路】:因为询问次数较多,对于每个询问都从起点到终点求最短路会超时。注意到对于任何一个询问终点都唯一,因此可以将转为求终点到平面上任何一个点的最少步数。可以用结构体表示每个位置的状态(包括位置、横卧或者竖立状态、目前所用步数),用 dist[x][y][3] 表示每种状态到达终点的最短步数(初始化为 −1-1−1表示不可到达),使用 bfs 求终点到其他任何一个点的最少步数即可
【核心代码】:
struct S{
int x, y, st, cnt;
};
void solve(){
int n, m;
std::cin >> n >> m;
std::vector<std::string> g(n);
for (int i = 0; i < n; i++)std::cin >> g[i];
std::vector<std::vector<std::array<int, 3>>> dist(N, std::vector<std::array<int, 3>>(N, {-1, -1, -1}));
auto check = [&](int x, int y) -> bool{
return x >= 0 && x < n && y >= 0 && y < m && g[x][y] != '0';
};
auto bfs = [&]() -> void{
std::queue<S> q;
int tx = -1, ty = -1;
for (int i = 0; i < n; ++i){
for (int j = 0; j < m; ++j){
if (g[i][j] == '3'){
tx = i;
ty = j;
break;
}
}
}
dist[tx][ty][0] = 0;
q.push({tx, ty, 0, 0});
while (!q.empty()){
auto [x, y, st, cnt] = q.front();
q.pop();
if (st == 0){
if (check(x, y - 1) && check(x, y - 2) && dist[x][y - 2][1] == -1){
dist[x][y - 2][1] = cnt + 1;
q.push({x, y - 2, 1, cnt + 1});
}
if (check(x, y + 1) && check(x, y + 2) && dist[x][y + 1][1] == -1){
dist[x][y + 1][1] = cnt + 1;
q.push({x, y + 1, 1, cnt + 1});
}
if (check(x - 1, y) && check(x - 2, y) && dist[x - 2][y][2] == -1){
dist[x - 2][y][2] = cnt + 1;
q.push({x - 2, y, 2, cnt + 1});
}
if (check(x + 1, y) && check(x + 2, y) && dist[x + 1][y][2] == -1){
dist[x + 1][y][2] = cnt + 1;
q.push({x + 1, y, 2, cnt + 1});
}
}
else if (st == 1){
// 同上
}
else{
// 同上
}
}
};
bfs();
int q;
std::cin >> q;
while (q--){
int x, y, s;
std::cin >> x >> y >> s;
x--;
y--;
bool f = false;
if (s == 0) f = check(x, y) && g[x][y] != '2';
else if (s == 1) f = check(x, y) && check(x, y + 1);
else f = check(x, y) && check(x + 1, y);
std::cout << (f ? dist[x][y][s] : -1) << '\n';
}
}
1892

被折叠的 条评论
为什么被折叠?



