【解题报告】RbOI Round 1,A&D题解

【RbOI R1】A&D 题解

其他题题解请移步 BC

点击图片跳转比赛:

A.Anxious Robin

从左到右扫一遍,按照题意模拟即可。

这里解释一下我的代码:

因为只判断了六种字母,所以遇到 - 会直接过滤,无需特判。

展开代码
#include <bits/stdc++.h>
#define ll long long
#define MyWife Cristallo
using namespace std;
char c[25];
int main() {
	scanf("%s", c);
	for(int i = 0; i < strlen(c); ++i) {
		if(c[i] == 'A') putchar('5');
		else if(c[i] == 'D') putchar('4');
		else if(c[i] == 'G') putchar('3');
		else if(c[i] == 'B') putchar('2');
		else if(c[i] == 'E') {
			if(c[i + 1] == '-') putchar('6');
			else putchar('1');
		}
	}
	return 0;
}

D.Sleepy Robin

给的其实是一个无向完全图,求的其实是一个最小生成树。

我们把每件事抽象成一个点,消耗的额外体力抽象成\长为 \(a_{i,j}\) 的边(断句已给出)。容易发现,题目其实是求留下 \((N-1)\) 条边,使 \(N\) 个点联通,并使所选边的边权和最小。

对此,我们有两种算法,\(Kruskal\)\(Prim\) 别惦记你内破博客了

个人感觉 \(Prim\)\(Kruskal\) 好理解,看个人选择罢,反正左右都是贪心。

\(Kruskal\) ver.

展开代码
#include <bits/stdc++.h>
#define ll long long
#define MyWife Cristallo
using namespace std;
const int N = 1e5 + 5; 
int n, F[N], ans, cnt; 
struct edge {
    int u, v, w;
} e[N];
bool cmp(edge a, edge b) {
    return a.w < b.w; 
} 
int find(int x) {
    if(F[x] == x) return x;
    return F[x] = find(F[x]);
}
int weal, tot;
void kruskal() {
    sort(e + 1, e + 1 + tot, cmp); 
    for(int i = 1; i <= tot; ++i) {
        int fa_u = find(e[i].u), fa_v = find(e[i].v); 
        if(fa_u == fa_v) continue;
        ans += e[i].w, F[fa_u] = fa_v; 
        if(++cnt == n - 1) return;
    }
}
int main() {
//	freopen("D10.in", "r", stdin);
//	freopen("D10.out", "w", stdout);
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) F[i] = i;
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= n; ++j) {
            scanf("%d", &weal);
            if(i != j) e[++tot].u = i, e[tot].v = j, e[tot].w = weal;
        }
    }
    kruskal();
    printf("%d\n", ans);
    return 0;
}

\(Prim\) ver.

展开代码
#include <bits/stdc++.h>
#define ll long long
#define MyWife Cristallo
using namespace std;
const int N = 1e5 + 5;
int n, m, s, ans, aans = 0x7fffffff;
int head[N], to[2 * N], weal[2 * N], dis[N], nxt[2 * N], tot;
bool vis[N];
void add(int u, int v, int w) {
    to[++tot] = v;
    weal[tot] = w;
    nxt[tot] = head[u];
    head[u] = tot;
}
struct node {
    int dis, pos;
};
bool operator < (const node &x, const node &y) {
    return x.dis > y.dis;
}
priority_queue<node> q;
inline void prim() {
//    for(int i = 1; i <= n; ++i) dis[i] = 0x7fffffff;
//    ans = 0x7fffffff;
//    while(!q.empty()) q.pop();
    int cnt = 0;
    dis[s] = 0;
    q.push((node){0, s});
    while(!q.empty()) {
        node tem = q.top();
        q.pop();
        int x = tem.pos, d = tem.dis;
        if(vis[x]) continue;
        vis[x] = 1, ++cnt;
        ans += d;
        for(int i = head[x]; i; i = nxt[i]) {
            int y = to[i], w = weal[i];
            if(dis[y] > w) {
                dis[y] = w;
                if(!vis[y]) q.push((node){dis[y], y});
            }
        }
    }
    if(cnt < n) ans = 0x7fffffff;
}
int main() {
//	freopen("D01.in", "r", stdin);
    scanf("%d", &n);
    int w;
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= n; ++j) {
            scanf("%d", &w);
            if(i != j) {add(i, j, w); add(j, i, w);}
        }
    }
    for(int i = 1; i <= n; ++i) dis[i] = 0x7fffffff;
    s = 1; 
	prim();
    printf("%d\n", ans);
    return 0;
}

彩蛋

image
image

posted @ 2024-04-07 18:54  _Kiichi  阅读(20)  评论(3编辑  收藏  举报