【解题报告】Codeforces Round #375 (Div. 2)

来源:互联网 发布:淘宝网夏季中年女装 编辑:程序博客网 时间:2024/05/16 18:32

题目链接


A. The New Year: Meeting Friends(Codeforces 723A)

思路

因为所求的坐标的范围比较小,因此直接枚举这个坐标,同时更新答案即可。

代码

#include <bits/stdc++.h>using namespace std;int a, b, c, res, ans;int main() {    scanf("%d%d%d", &a, &b, &c);    ans = 400;    for(int i = 1; i <= 100; i++) {        res = abs(a - i) + abs(b - i) + abs(c - i);        ans = min(res, ans);    }    printf("%d\n", ans);    return 0;}

B. Text Document Analysis(Codeforces 723B)

思路

首先将括号外的字符串和括号内的字符串分离开。方法是先定位所有括号,然后将所有括号中的字符串用 _ 字符连接起来放在一个新的字符串中,再用 _ 字符将原字符串中括号中的字符串(包括括号)屏蔽掉。
接着将两个字符串中非字母的字符改成空格,并将他们分别制作成字符串流,最后从字符串流中边输入边统计即可得到答案。

代码

#include <bits/stdc++.h>using namespace std;int n, idx, x, y;string s, t;int main() {    ios_base::sync_with_stdio(false);    cin >> n >> s;    for(int i = 0; i < n; i++) {        if(s[i] == '(') {            idx = i;        }        if(s[i] == ')') {            t = t + "_" + s.substr(idx + 1, i - idx - 1);            for(int j = idx; j <= i; j++) {                s[j] = '_';            }        }    }    for(int i = 0; i < s.size(); i++) {        if(s[i] == '_' || s[i] == '(' || s[i] == ')') {            s[i] = ' ';        }    }    for(int i = 0; i < t.size(); i++) {        if(t[i] == '_' || t[i] == '(' || t[i] == ')') {            t[i] = ' ';        }    }    stringstream in(t);    stringstream out(s);    while(out >> s) {        x = max(x, (int)s.size());    }    while(in >> s) {        y++;    }    cout << x << ' ' << y << endl;    return 0;}

C. Polycarp at the Radio(Codeforces 723C)

思路

首先肯定可以将所有不是编号 1m 乐队演奏的歌曲都改成 1m 的。那么最好的情况肯定是所有的歌曲都是 1m 乐队演奏的。为了让演奏曲目最少的乐队的演奏曲目最多,应该把 n 个曲目让 m 个乐队均摊演奏。那么每个乐队至少获得 n/m 首音乐的演奏机会。
接下来的事情就简单了,我们先枚举不是 1m 乐队演奏的音乐,将其改成 1m 乐队中演奏数目最少的乐队演奏的曲目。然后再枚举所有曲目,将演奏曲目超过 n/m 首的乐队的曲目分配给演奏数最少的乐队。
实现上,为了动态了解那个乐队的演奏曲目最少,可以用堆将每个乐队对曲目的“需求”维护起来(但是这题的数据量比较小,貌似暴力也行)。

代码

#include <bits/stdc++.h>using namespace std;typedef pair <int, int> p;const int maxn = 2010;int n, m, need, cnt, idx, dif, a[maxn], b[maxn];priority_queue <p> pq;int main() {    scanf("%d%d", &n, &m);    for(int i = 1; i <= n; i++) {        scanf("%d", &a[i]);        if(a[i] <= m) {            b[a[i]]++;        }    }    need = n / m;    for(int i = 1; i <= m; i++) {        if(b[i] < need) {            pq.push(p(need - b[i], i));        }    }    for(int i = 1; i <= n; i++) {        if(pq.empty()) {            break;        }        if(a[i] > m) {            p tmp = pq.top();            pq.pop();            idx = tmp.second;            dif = tmp.first;            a[i] = idx;            b[idx]++;            cnt++;            if(dif > 1) {                pq.push(p(dif - 1, idx));            }        }    }    for(int i = 1; i <= n; i++) {        if(pq.empty()) {            break;        }        if(b[a[i]] > need) {            p tmp = pq.top();            pq.pop();            idx = tmp.second;            dif = tmp.first;            b[a[i]]--;            b[idx]++;            a[i] = idx;            cnt++;            if(dif > 1) {                pq.push(p(dif - 1, idx));            }        }    }    printf("%d %d\n", need, cnt);    for(int i = 1; i <= n; i++) {        printf("%d ", a[i]);    }    puts("");    return 0;}

D. Lakes in Berland(Codeforces 723D)

思路

先用 DFS 遍历图,找出所有的湖(注意临海的水域不算湖)。对于每个湖记录其中的一个坐标和其面积。然后根据面积对湖排序,找到面积最小的几个湖,用 DFS 的方法从之前记录的坐标开始填湖。最后输出图即可。

代码

#include <bits/stdc++.h>using namespace std;// 将与湖有关的信息封装起来以便排序struct lake {    int x, y, area;    lake() {}    lake(int x, int y, int area): x(x), y(y), area(area) {}    bool operator < (const lake& o) const {        return area < o.area;    }};const int maxn = 60;const int dx[] = {-1, 1, 0, 0};const int dy[] = {0, 0, -1, 1};bool vis[maxn][maxn];char G[maxn][maxn];int n, m, k, res, ans, del;vector <lake> v;// 在图中找连通分量(湖)int dfs(int x, int y) {    vis[x][y] = true;    // 如果临海的话就返回-1    if(G[x][y] == 0) {        return -1;    }    int res = 0;    bool ok = true;    // 向四个相邻的方向走    for(int i = 0; i < 4; i++) {        int nx = x + dx[i];        int ny = y + dy[i];        if(G[nx][ny] == '*' || vis[nx][ny]) {            continue;        }        int t = dfs(nx, ny);        // 如果发现临海就标记一下        if(t == -1) {            ok = false;        }        res += t;    }    return ok ? res + 1 : -1;}// 在图中填湖void land(int x, int y) {    G[x][y] = '*';    for(int i = 0; i < 4; i++) {        int nx = x + dx[i];        int ny = y + dy[i];        if(G[nx][ny] != '*') {            land(nx, ny);        }    }}int main() {    scanf("%d%d%d", &n, &m, &k);    for(int i = 1; i <= n; i++) {        scanf("%s", G[i] + 1);    }    for(int i = 1; i <= n; i++) {        for(int j = 1; j <= m; j++) {            if(G[i][j] == '*' || vis[i][j]) {                continue;            }            res = dfs(i, j);            if(res == -1) {                continue;            }            v.push_back(lake(i, j, res));        }    }    del = v.size() - k;    // 按照面积对湖排序    sort(v.begin(), v.end());    for(int i = 0; i < del; i++) {        ans += v[i].area;        land(v[i].x, v[i].y);    }    printf("%d\n", ans);    for(int i = 1; i <= n; i++) {        printf("%s\n", G[i] + 1);    }    puts("");    return 0;}

E. One-Way Reform(Codeforces 723E)

思路

首先显然每个偶度数的点都能够达到入度等于出度的状态。奇度数的点则必然不行。但是奇度数的点可以配合偶度数的点使其达到入度等于出度的状态。
这样的状态让我们想起欧拉回路。
正好对于每个连通分量奇度数的点的数量都是偶数。那么我们对奇度数的点之间建立无向边。这样原图就变成能够构成欧拉回路的图(正好各个连通分量之间也连通了)。实现起来是设置一个虚拟节点 0 ,让所有奇度数的点向这个点连无向边。
最后在用 DFS 访问欧拉回路的同时输出访问的边的方向即可(注意要标记已经访问过的边)。

代码

#include <bits/stdc++.h>using namespace std;const int maxn = 205;bool vis[maxn][maxn];int t, n, m, u, v, ans;vector <int> G[maxn];void dfs(int u) {    for(int i = 0; i < G[u].size(); i++) {        int v = G[u][i];        if(vis[u][v]) {            continue;        }        vis[u][v] = vis[v][u] = true;        if(u > 0 && v > 0) {            printf("%d %d\n", u, v);        }        dfs(v);    }}int main() {    scanf("%d", &t);    while(t--) {        scanf("%d%d", &n, &m);        for(int i = 0; i <= n; i++) {            G[i].clear();        }        for(int i = 0; i < m; i++) {            scanf("%d%d", &u, &v);            G[u].push_back(v);            G[v].push_back(u);        }        ans = 0;        for(int i = 1; i <= n; i++) {            if(G[i].size() & 1) {                G[0].push_back(i);                G[i].push_back(0);            }            else {                ans++;            }        }        printf("%d\n", ans);        memset(vis, 0, sizeof(vis));        for(int i = 1; i <= n; i++) {            dfs(i);        }    }    return 0;}

0 0
原创粉丝点击