Educational Codeforces Round 124 (Rated for Div. 2) CD题解

C-Fault-tolerant Network

题目大意:
有两列主机,每一列的主机相邻之间有网络连线,但是两列之间的主机没有网络连线,现在将两列之间的主机进行连接,使得任意一台主机断开后整个网络还是能连通。输出最小的费用,连接两台主机的费用为 ∣ a i − b i ∣ |a_i-b_i| aibi

思路:
显然每一列的头尾主机都要与另一列有连接。
如果只是贪心地求出头尾主机连接对面主机的最小费用,可能会存在连接重合或者不是最优解的情况。
比如有的时候连接两条不是最小费用的线比连接三条最小费用的线花费更少。
因为只有四台主机需要连接,所以直接枚举这四台主机的连接情况即可,一个主机对应三种连接情况:连对面第一台,连对面最后一台,连对面中间花费最小的一台。
枚举第一列的头尾主机连接后就可以确定另一列的头尾主机怎么连了。

AC代码:

#include <bits/stdc++.h>
const long long inf = 1e18;
const int N = 2e5 + 5;
using namespace std;

int a[N], b[N];

long long ca1[4], ca2[4], cb1[4], cb2[4];

void solve()
{
    int n;
    long long ans = inf;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
        cin >> b[i];

    ca1[1] = abs(a[1] - b[1]);
    ca1[3] = abs(a[1] - b[n]);
    ca2[1] = abs(a[n] - b[1]);
    ca2[3] = abs(a[n] - b[n]);
    cb1[1] = abs(b[1] - a[1]);
    cb1[3] = abs(b[1] - a[n]);
    cb2[1] = abs(b[n] - a[1]);
    cb2[3] = abs(b[n] - a[n]);
    ca1[2] = ca2[2] = cb1[2] = cb2[2] = inf;
    for (int i = 1; i <= n; i++)
    {
        if (abs(a[1] - b[i]) < ca1[2]) ca1[2] = abs(a[1] - b[i]);
        if (abs(a[n] - b[i]) < ca2[2]) ca2[2] = abs(a[n] - b[i]);
        if (abs(b[1] - a[i]) < cb1[2]) cb1[2] = abs(b[1] - a[i]);
        if (abs(b[n] - a[i]) < cb2[2]) cb2[2] = abs(b[n] - a[i]);
    }
    for (int a1 = 1; a1 <= 3; a1++) //1表示连对面第一台,2表示连中间花费最小的的,3表示连对面最后一台
    {
        for (int a2 = 1; a2 <= 3; a2++)
        {
            long long tmp = ca1[a1] + ca2[a2];
            if (a1 != 1 && a2 != 1) tmp += min({cb1[1], cb1[2], cb1[3]});
            if (a1 != 3 && a2 != 3) tmp += min({cb2[1], cb2[2], cb2[3]});
            ans = min(ans, tmp);
        }
    }
    cout << ans << "\n";
}
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while (T--)
        solve();
    return 0;
}

D-Nearest Excluded Points

题目大意:
给定一个点集,求出每个点在点集以外曼哈顿距离最小的点。

思路:
如果一个点的上下左右有至少一个点是不在点集中的,那么这个点就是最小的曼哈顿距离点。
对于那些四周的点都在点集中的,将四周的点确定后就可以确定中间点的最小曼哈顿距离点。
就是一个BFS的过程,先将外围一圈的点入队,接着将里面一圈的点再入队。也可以先将不在点集中,但是与点集中的点相邻的点入队。因为坐标范围比较大,需要用pair<int,int>map进行存储
同时记录一下每个点的最小曼哈顿点。

AC代码:

#include <bits/stdc++.h>
const int N = 2e5 + 5;
using namespace std;
typedef pair<int, int> PII;
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
int x[N], y[N];
int n, xx, yy;
map<PII, bool> vis, inset;
map<PII, PII> root; //记录每个点的最小曼哈顿点
queue<PII> q;

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n; ++i)
    {
        cin >> x[i] >> y[i];
        inset[{x[i], y[i]}] = 1;
    }

    for (int i = 1; i <= n; ++i) //先将不在点集中,但是与点集中的点相邻的点入队
    {
        for (int j = 0; j < 4; j++)
        {
            xx = x[i] + dx[j];
            yy = y[i] + dy[j];
            if (!inset.count({xx, yy}) && !vis[{xx, yy}])
            {
                q.push({xx, yy});
                root[{xx, yy}] = {xx, yy};
                vis[{xx, yy}] = 1;
            }
        }
    }
    int cnt = 0;
    while (q.size())
    {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            xx = x + dx[i];
            yy = y + dy[i];
            if (inset.count({xx, yy}) && !vis[{xx, yy}])
            {
                vis[{xx, yy}] = 1;
                root[{xx, yy}] = root[{x, y}];
                q.push({xx, yy});
                cnt++;
            }
        }
        if (cnt == n) break;
    }
    for (int i = 1; i <= n; i++)
        cout << root[{x[i], y[i]}].first << " " << root[{x[i], y[i]}].second << "\n";
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值