码迷,mamicode.com
首页 > 其他好文 > 详细

18.10.02 画作

时间:2019-04-02 19:45:36      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:比较   max   printf   pen   empty   va_arg   iterator   href   转化   

题面

/*
------------------------------------
画作
不难证明猜到一个这样的结论: 存在一种最优方案使得每次操作的区
域是上一次的子集且颜色与上一次相反.

考虑归纳证明, 记 S 为当前所有操作区域的并, T 为接下来一步的操作
区域, 我们有:
1. T 与 S 有交的情况一定可以转化成 T 被 S 包含的情况.
2. T 与 S 交集为空时, 可以找一个连接 S 和 T 的集合 M 并操作 S ∪
T ∪ M , 并将之前的所有操作连接到更外的层以及外层的连接部分同时
操作, 特殊处理最外层和第二层的情况.
3. T 被 S 包含时, T 落在某个完整区域内时等价于情况二, 否则一定连
接若干个同色块, 这些块可以同时处理, 步数一定不会更劣.

知道这个结论就比较好做了, 我们可以枚举最后被修改的区域, 这时答
案就是将同色边边权当作 0, 异色边边权当作 1 后距离这个点最远的黑色点
的距离, 对所有点取最小值即可.
r, c ≤ 50.
------------------------------------2018.10.5

其实这个结论是比较好想的,关键是怎么实现,这里有一个经典的方法:
同颜色边权为0,不同颜色边权为1,然后用deque跑bfs就可以了
考虑怎么理解这道题:
枚举最后被修改的区域,答案就是离它最远的黑色点的距离.
这个dis代表需要这么多步<产生只有一个黑块的状态,再加1步全部换成白色>

------------------------------------2018.11.5

*/
#include <bits/stdc++.h>

using std::pair;
using std::vector;
using std::string;

typedef long long ll;
typedef pair<int, int> pii;

#define fst first
#define snd second
#define pb(a) push_back(a)
#define mp(a, b) std::make_pair(a, b)
#define debug(...) fprintf(stderr, __VA_ARGS__)

template <typename T> bool chkmax(T& a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> bool chkmin(T& a, T b) { return a > b ? a = b, 1 : 0; }

const int oo = 0x3f3f3f3f;

string procStatus() {
    std::ifstream t("/proc/self/status");
    return string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());
}

template <typename T> T read(T& x) {
    int f = 1; x = 0;
    char ch = getchar();
    for(;!isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    return x *= f;
}

const int N = 50;

int n, m;
char g[N + 5][N + 5];
int dis[N + 5][N + 5];

const int dx[] = { 1, 0, -1, 0 };
const int dy[] = { 0, 1, 0, -1 };

int bfs(int x, int y) {//最简单的广搜,边权0或1用双端队列deque
    std::deque<pii> q;
    memset(dis, -1, sizeof dis);

    dis[x][y] = 0;
    q.push_back(mp(x, y));

    int res = 0;
    while(!q.empty()) {
        int cx = q.front().fst, cy = q.front().snd;

        if(g[cx][cy] == '1')
            chkmax(res, dis[cx][cy]);

        q.pop_front();
        for(int i = 0; i < 4; ++i) {
            int nx = cx + dx[i], ny = cy + dy[i];

            if(nx >= 0 && nx < n && ny >= 0 && ny < m && dis[nx][ny] == -1) {

                if(g[nx][ny] == g[cx][cy]) {
                    dis[nx][ny] = dis[cx][cy];
                    q.push_front(mp(nx, ny));
                } else {
                    dis[nx][ny] = dis[cx][cy] + 1;
                    q.push_back(mp(nx, ny));
                }
            }
        }
    }
    return res;
}

int main() {
    //freopen("paint.in", "r", stdin);
    //freopen("paint.out", "w", stdout);

    read(n), read(m);
    for(int i = 0; i < n; ++i) {
        scanf("%s", g[i]);
    }

    int ans = oo;
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            chkmin(ans, bfs(i, j));
        }
    }
    printf("%d\n", ans + 1);

    return 0;
}

18.10.02 画作

标签:比较   max   printf   pen   empty   va_arg   iterator   href   转化   

原文地址:https://www.cnblogs.com/lizehon/p/10644762.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!