【解題報告】Codeforces Round #375 (Div. 2)

題目鏈接


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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章