2025睿抗省赛题解

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 点格棋

【题目大意】:给出一个下点格棋的规则,判断每一步下棋是否满足规则,以及求出最终获胜者及其得分(成功连成一个小方格即可得分)
【解题思路】:需要注意的点有很多,主要有以下点:

  1. 第一轮是否为小 A 先手
  2. 两点所连成的线是否已经在之前连过
  3. 是否为垂直或水平,且长度为 111 的线
  4. 所连的线是否超出棋盘
  5. 去掉不合法的步骤后,是否满足小 A 和小 B 依次下棋
  6. 成功连成一个小方格后可以额外在进行一个回合
    下面提供的代码用 mp 记录某条线是否已经被连接过,用 g[x][y] 表示格点 g[x - 1][y - 1]g[x][y - 1]g[x - 1][y]g[x][y] 是否已成功被连接。成功被连接后赋值为 −1-11
    【核心代码】:
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 - 1n1 个节点 m−2m - 2m2 条边的树);
  • 当图中不存在环或仅存在一种环(即不存在次大环)时,则不能按照上面找环的办法来求解(注意到环一定满足题目的两个条件,但满足题目两个条件的不一定是环)。此时如果图中存在一条边,可以证明这条边所连接的两个点构成的子图也满足题目的两个条件(容易证明更长的链或者其他非环子图都不满足题意);
  • 如果图中不存在任何边(题目中数据范围为 n≥1,  m≥0n \ge 1,\,\ m \ge 0n1, m0),一个节点构成的图也满足题目条件(删除这个节点后图中不存在节点,即空树)

【核心代码】:

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(n0)个结点的有限集 。当 n=0n = 0n=0 时,称为空树。在任意一棵非空树中应满足:

  1. 有且仅有一个特定的称为根的结点;
  2. 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-11
平面上有三种格子:坚实格、易碎格和空格。
坚实格:可以作为横卧时的两个支撑格之一,或者作为长方块竖立时唯一的支撑格。
易碎格:可以作为横卧时的两个支撑格之一,不能作为长方块竖立时唯一的支撑格。
空 格:长方块的任何部分都不能位于空格之上。
【解题思路】:因为询问次数较多,对于每个询问都从起点到终点求最短路会超时。注意到对于任何一个询问终点都唯一,因此可以将转为求终点到平面上任何一个点的最少步数。可以用结构体表示每个位置的状态(包括位置、横卧或者竖立状态、目前所用步数),用 dist[x][y][3] 表示每种状态到达终点的最短步数(初始化为 −1-11表示不可到达),使用 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';
    }
}
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值