arc177 | 賽後vp

你说得太对辣發表於2024-05-13

當時在車上,回家之後補的。

a.

從高到底依次列舉硬幣價格判斷即可。

b.

每次從後找一段連續段的0/1的右端點,設位置為 \(pos\),操作其對應的 \(pos + 1\) 次即可。

\(s[pos + 1]\)\(s[pos]\) 相反,所以上次操作後,前面的 \(pos\) 個都為 \(s[pos + 1]\),因此操作 \(pos + 1\) 能把 \([0,pos]\) 全變成 \(s[pos]\)

最劣情況下需要操作 \(\frac{n(n+1)}{2}\) 次。

程式碼(寫的很醜別噴)

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 7;
struct node {
    int a, b;
};
vector<node> v;
int main() {
    int n;
    string s;
    cin >> n >> s;
    int ans = 0;
    int pos = 0;
    for(int i = 0; i < n; i ++) {
        if(s[i] == '1') pos = i;
    }
    int cnt = 0;
    int flag = 0;
    for(int i = pos; i >= 0; i --) {
        if(flag == s[i] - '0') {
            continue;
        }
        flag = s[i] - '0';
        v.push_back({i + 1, s[i] - '0'});
        ans += i + 1;
    }
    cout << ans << endl;
    for(auto i : v) {
        if(i.b == 1) {
            for(int j = 1; j <= i.a; j ++) cout << "A";
        }
        else {
            for(int j = 1; j <= i.a; j ++) cout << "B";
        }
    }
}

c.

即為求從 \((1,1)\) 走到 \((n,n)\) 經過的最少的藍色的數量與從 \((1,n)\) 走到 \((n,1)\) 經過最少的紅色的數量的和。對於這個,可以每個點向周圍四個點連邊,建圖。總點數 \(n^2\),總邊數 \(m = 4n^2\),可以透過。

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 7;
string s[505];
int head[N], ecnt;
int dis[N], vis[N];
struct edge {
    int next, to, val;
}e[N];
void addedge(int u, int v, int w) {
    e[++ ecnt].to = v;
    e[ecnt].next = head[u];
    e[ecnt].val = w;
    head[u] = ecnt;
}
struct Dis {
    int u, val;
    friend bool operator < (const Dis a, const Dis b) {
        return a.val > b.val;
    }
};
void dij(int s) {
    priority_queue<Dis> q;
    memset(dis, 0x3f, sizeof dis);
    dis[s] = 0;
    q.push({s, dis[s]});
    while(!q.empty()) {
        int u = q.top().u;
        q.pop();
        if(vis[u]) continue;
        vis[u] = 1;
        for(int i = head[u]; ~i; i = e[i].next) {
            int v = e[i].to;
            if(dis[v] > dis[u] + e[i].val) {
                dis[v] = dis[u] + e[i].val;
                q.push({v, dis[v]});
            }
        }
    }
} 

int main() {
    memset(head, -1, sizeof head);
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++) {
        cin >> s[i];
        s[i] = ' ' + s[i];
    }
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= n; j ++) {
            if(i == n && j == n) continue;
            if(s[i][j] == 'R') {
                if(j != n) addedge((i - 1) * n + j, (i - 1) * n + j + 1, s[i][j] != s[i][j + 1]);
                if(i != n) addedge((i - 1) * n + j, i * n + j, s[i][j] != s[i + 1][j]);
                if(i != 1) addedge((i - 1) * n + j, (i - 2) * n + j, s[i - 1][j] != s[i][j]);
                if(j != 1) addedge((i - 1) * n + j, (i - 1) * n + j - 1, s[i][j] != s[i][j - 1]);
            }
            else {
                if(j != n) addedge((i - 1) * n + j, (i - 1) * n + j + 1, s[i][j + 1] != 'R');
                if(i != n) addedge((i - 1) * n + j, i * n + j, s[i + 1][j] != 'R');
                if(i != 1) addedge((i - 1) * n + j, (i - 2) * n + j, s[i - 1][j] != 'R');
                if(j != 1) addedge((i - 1) * n + j, (i - 1) * n + j - 1, s[i][j - 1] != 'R');
            }
        }
    }
    dij(1);
    int cnt = dis[n * n];
    memset(head, -1, sizeof head);
    ecnt = 0;
    memset(vis, 0, sizeof vis);
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= n; j ++) {
            if(i == n && j == n) continue;
            if(s[i][j] == 'B') {
                if(j != n) addedge((i - 1) * n + j, (i - 1) * n + j + 1, s[i][j] != s[i][j + 1]);
                if(i != n) addedge((i - 1) * n + j, i * n + j, s[i][j] != s[i + 1][j]);
                if(i != 1) addedge((i - 1) * n + j, (i - 2) * n + j, s[i - 1][j] != s[i][j]);
                if(j != 1) addedge((i - 1) * n + j, (i - 1) * n + j - 1, s[i][j] != s[i][j - 1]);
            }
            else {
                if(j != n) addedge((i - 1) * n + j, (i - 1) * n + j + 1, s[i][j + 1] != 'B');
                if(i != n) addedge((i - 1) * n + j, i * n + j, s[i + 1][j] != 'B');
                if(i != 1) addedge((i - 1) * n + j, (i - 2) * n + j, s[i - 1][j] != 'B');
                if(j != 1) addedge((i - 1) * n + j, (i - 1) * n + j - 1, s[i][j - 1] != 'B');
            }
        }
    }
    dij(n);
    cout << cnt + dis[(n - 1) * n + 1];
    return 0;
}

相關文章