• AtCoder Grand Contest 004 CDEF


    AGC004

    C - AND Grid

    构造题。染色方案要求四联通,边界的行、列提供了一个很好的连通介质,且题目保证给定网格图中边界都为 (.)

    具体做法:第一张图中把最左边一列涂黑,第二张图把最右边一列涂黑,当然必须涂黑的两张图中都涂黑。然后第一张图中把偶数行全部涂黑,第二张图把奇数行全部涂黑,既满足了连通性,又不会与条件冲突

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 505;
    int h, w; char c[N][N], a[N][N], b[N][N];
    signed main() {
        scanf ("%d %d", &h, &w);
        for (int i = 1; i <= h; ++i)
            scanf ("%s", c[i] + 1);
        for (int i = 1; i <= h; ++i)
            for (int j = 1; j <= w; ++j) a[i][j] = b[i][j] = c[i][j];
        for (int i = 1; i <= h; ++i) a[i][1] = '#', b[i][w] = '#';
        for (int i = 1; i <= h; i += 2)
            for (int j = 2; j < w; ++j) a[i][j] = '#';
        for (int i = 2; i <= h; i += 2)
            for (int j = 2; j < w; ++j) b[i][j] = '#';
        for (int i = 1; i <= h; ++i) {
            for (int j = 1; j <= w; ++j) putchar (a[i][j]); puts ("");
        } puts ("");
        for (int i = 1; i <= h; ++i) {
            for (int j = 1; j <= w; ++j) putchar (b[i][j]); puts ("");
        }
        return 0;
    }
    

    D - Teleporter

    原图构成一棵基环内向树。所有点到 (1) 的距离要相同,可以想象,一定是先跳到 (1) 然后在原地跳若干次(可以为 (0)),那么 (1) 必须连向自己。还有一个条件是所有点到 (1) 的距离不能 (>k),贪心的进行一遍 (dfs)(1) 连向自己,此时已经变成一棵树),当发现距离(深度)不满足条件就把答案 (+1),然后把深度改成 (1)

    代码中的分类讨论应该是多次一举,不必理会

    #include <bits/stdc++.h>
    using namespace std;
    void read (int &x) {
        char ch = getchar(); x = 0; while (!isdigit(ch)) ch = getchar();
        while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
    } const int N = 1e5 + 5;
    int n, k, res, d[N], a[N]; vector<int> g[N];
    void dfs (int u, int dp) {
        d[u] = dp;
        for (int v : g[u]) dfs (v, dp + 1), d[u] = max (d[u], d[v]);
        if (d[u] - dp == k - 1 && d[u] > k) ++res, d[u] = 0;
    }
    signed main() {
        read (n), read (k);
        for (int i = 1; i <= n; ++i) read (a[i]);
        if (k == 1) {
            for (int i = 1; i <= n; ++i) if (a[i] != 1) ++res;
        } else {
            if (a[1] != 1) ++res, a[1] = 1;
            for (int i = 2; i <= n; ++i)
                g[a[i]].push_back (i); dfs (1, 0);
        }
        return printf ("%d
    ", res), 0;
    }
    

    E - Salvage Robots

    非常“暴力”的动态规划。可以把机器人走动的过程想成一个框在动,机器人不动。如果机器人出框就挂了,和框的中心 (E) 重合就 (win) 了。(f_{l,r,u,d}) 表示框向左最多移动 (l),(向右向上向下同理)能获得的最大分数,但是转移的情况比较复杂就算了吧。。。不如看这个

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 105;
    int n, m; char ch[N][N]; short res, f[N][N][N][N], p[N][N], q[N][N];
    #define now f[a][b][c][d]
    #define down f[a + 1][b][c][d]
    #define up f[a][b][c + 1][d]
    #define right f[a][b + 1][c][d]
    #define left f[a][b][c][d + 1]
    signed main() {
        cin >> n >> m; int x = 0, y = 0;
        for (int i = 1; i <= n; ++i) scanf ("%s", ch[i] + 1);
        for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) {
            if (ch[i][j] == 'E') x = i, y = j;
            p[i][j] = p[i][j - 1] + (ch[i][j] == 'o');
            q[i][j] = q[i - 1][j] + (ch[i][j] == 'o');
        }
        for (int a = 0; a <= n - x; ++a)         // 向下
        for (int b = 0; b <= m - y; ++b)         // 向右
        for (int c = 0; c < x; ++c)              // 向上
        for (int d = 0; d < y; ++d) {            // 向左
            res = max (res, now);
            if (x + a < n - c) down = max ((int)down, (int)now + p[x + a + 1][min (m - d, y + b)] - p[x + a + 1][max (b, y - d - 1)]);
            if (x - c > a + 1) up = max ((int)up, (int)now + p[x - c - 1][min (m - d, y + b)] - p[x - c - 1][max (b, y - d - 1)]);
            if (y + b < m - d) right = max ((int)right, (int)now + q[min (n - c, x + a)][y + b + 1] - q[max (a, x - c - 1)][y + b + 1]);
            if (y - d > b + 1) left = max ((int)left, (int)now + q[min (n - c, x + a)][y - d - 1] - q[max (a, x - c - 1)][y - d - 1]);
        }
        cout << res << '
    ';
    }
    

    F - Namori

    “把相同颜色的相邻点反转”就很可怕,不如先考虑树的情况

    有一个有意思的转换:把树二分染色(为了区分,染成红蓝色),然后假设初始的时候每个红格里有一个球。每一步操作可以把这个球推向相邻的空格子

    为什么等价呢?把红格里有球看成原题中的白,红格无球看成黑,蓝格有球为黑,无球为白。每个状态和条件都是等价的。最终状态是所有白格有球,黑格无球

    转换后的问题没有那么恐怖。对每一条由 (x) 连向父亲的边进行考虑,发生在这条边上的移动次数至少是 (|num(黑格数)-num(白格数)|),因为数量都匹配不上肯定要进出。然后这移动次数为 (|num(黑格数)-num(白格数)|) 的方案也是可以精细构造出来的,树的情况就搞定啦

    基环树多出来了一条边。对这个环的长度奇偶讨论

    环长为偶数:此时仍然是二分图把环取出来,设环上每条边的流量为 (x_i),每个点进出平衡,可以列出方程组。woc这个东西相当于数轴上有 (m) 个村庄,要选一个点使到所有村庄的距离和最小,然后带入中间那个就好了。

    环长为奇数:此时多出来的边连接的两个点颜色相同,如果在这条边上操作一次就是同时产生两个球或吃掉两个球。前面的情况如果黑白格数量不同一定无解,但这种情况同奇偶就可以。先进行多补少添的操作,然后和树的差不多,改一下环上点的值

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    void read (int &x) {
        char ch = getchar(); x = 0; while (!isdigit(ch)) ch = getchar();
        while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
    } const int N = 1e5 + 5, M = N << 1;
    int n, m, res, rt, qwq, c[N], f[N], fa[N];
    int cnt, h[N], to[M], nxt[M], p, a[N];
    void add (int u, int v) {
        to[++cnt] = v, nxt[cnt] = h[u], h[u] = cnt;
    }
    int get (int x) {
        return f[x] == x ? x : f[x] = get (f[x]);
    }
    void dfs (int u, int co) {
        for (int i = h[u], v; i; i = nxt[i]) {
            if ((v = to[i]) != fa[u]) fa[v] = u, dfs (v, -co), c[u] += c[v];
        } c[u] += co;
    }
    signed main() {
        read (n), read (m); rt = 1;
        for (int i = 1; i <= n; ++i) f[i] = i;
        for (int i = 1, u, v, fu, fv; i <= m; ++i) {
            read (u), read (v); fu = get (u), fv = get (v);
            if (fu == fv) rt = u, qwq = v;
            else add (u, v), add (v, u), f[fv] = fu;
        }
        dfs (rt, 1);
        if (m == n) {
            for (int i = qwq; i; i = fa[i]) a[++p] = c[i];
            if (p & 1) {
                if (c[rt] & 1) return puts ("-1"), 0;
                for (int i = qwq; i; i = fa[i]) c[i] -= c[rt] >> 1;
            } else {
                if (c[rt]) return puts ("-1"), 0;
                sort (a + 1, a + p + 1);
                for (int i = qwq; i; i = fa[i]) c[i] -= a[p >> 1];
            }
        } else if (c[rt]) return puts ("-1"), 0;
        for (int i = 1; i <= n; ++i) res += abs (c[i]);
        return printf ("%lld
    ", res), 0;
    }
    
  • 相关阅读:
    企业应用点点滴滴记入
    jQuery 图片轮播
    javascript setTimeout和setinterval的区别是?
    html5 新增的标签和废除的标签
    H​t​m​l​5​ ​学​习​:​H​T​M​L​5​新​增​结​构​标​签
    WEB前端开发人员须知的常见浏览器兼容问题及解决技巧
    jQuery 简单返回顶部代码
    css 背景色为半透明的例子
    javaScript面试题大全
    Ionic3学习笔记(五)动画之使用 animate.css
  • 原文地址:https://www.cnblogs.com/whx666/p/14269304.html
Copyright © 2020-2023  润新知