zoukankan      html  css  js  c++  java
  • UVA 10572 Black & White

    UVA_10572

        由于具有连通性的要求,所以可以用插头dp来处理,这样需要记录下来轮廓线上格子的颜色以及连通状况,在dp的时候需要考虑全面不合法的情况,具体的思路可以参考另一个题的题解:http://www.cnblogs.com/staginner/archive/2012/09/17/2688634.html。

        在最坏的情况下即8*8全部是'.',递推到每个格子的状态总数也没超过10000。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define HASH 10007
    #define MAXD 10010
    int N, M, pre[65][MAXD];
    char g[10][10], op[65][MAXD];
    struct HashMap
    {
        int head[HASH], size, next[MAXD], st[MAXD], col[MAXD], dp[MAXD];
        void init()
        {
            memset(head, -1, sizeof(head)), size = 0;    
        }
        void push(int _st, int _col, int _dp, int id, int k, char ch)
        {
            int i, h = ((_st << 6) + _col) % HASH;
            for(i = head[h]; i != -1; i = next[i])
                if(st[i] == _st && col[i] == _col)
                {
                    dp[i] += _dp;
                    return ;    
                }
            st[size] = _st, col[size] = _col, dp[size] = _dp;
            pre[id][size] = k, op[id][size] = ch;
            next[size] = head[h], head[h] = size ++;
        }
    }hm[2];
    int code[10], h[10];
    int encode(int *code, int m)
    {
        int i, st = 0, cnt = -1;
        memset(h, -1, sizeof(h));
        for(i = 0; i < m; i ++)
        {
            if(h[code[i]] == -1) h[code[i]] = ++ cnt;
            st = st << 3 | h[code[i]];    
        }
        return st;
    }
    void decode(int *code, int m, int st)
    {
        for(int i = m - 1; i >= 0; i --) code[i] = st & 7, st >>= 3;    
    }
    void init()
    {
        int i;
        scanf("%d%d", &N, &M);
        for(i = 0; i < N; i ++) scanf("%s", g[i]);    
    }
    void dp(int i, int j, int c, int cur)
    {
        int k;
        for(k = 0; k < hm[cur].size; k ++)
        {
            int col = hm[cur].col[k], u = i ? (col >> j & 1) == c : 0, l = j ? (col >> j - 1 & 1) == c : 0, lu = (col >> M) == c;    
            if(u && l && lu) continue;
            if(i == N - 1 && j == M - 1 && !u && !l && lu) continue;
            decode(code, M, hm[cur].st[k]);
            if(i && !u)
            {
                int s1 = 0, s2 = 0;
                for(int t = 0; t < M; t ++)
                {
                    if(code[t] == code[j]) ++ s1;
                    if((col >> t & 1) != c) ++ s2;    
                }
                if(s1 == 1)
                {
                    if(s2 > 1) continue;
                    if(i < N - 1 || j < M - 2) continue;    
                }
            }
            if(u && l)
            {
                if(code[j] != code[j - 1])
                    for(int t = 0, x = code[j]; t < M; t ++)
                        if(code[t] == x) code[t] = code[j - 1];    
            }
            else if(!u && l) code[j] = code[j - 1];
            else if(!u && !l) code[j] = M;
            
            if(col & 1 << j) col |= 1 << M;
            else col &= ~(1 << M);
            if(c) col |= 1 << j;
            else col &= ~(1 << j);
            
            hm[cur ^ 1].push(encode(code, M), col, hm[cur].dp[k], i * M + j, k, c ? '#' : 'o');
        }
    }
    void print(int k)
    {
        int i, j;
        for(i = N - 1; i >= 0; i --)
            for(j = M - 1; j >= 0; j --)
                g[i][j] = op[i * M + j][k], k = pre[i * M + j][k];
        for(i = 0; i < N; i ++) puts(g[i]);
    }
    void solve()
    {
        int i, j, k, cur = 0, ans = 0;
        hm[0].init();
        hm[0].push(0, 0, 1, 0, 0, 0);
        for(i = 0; i < N; i ++)
            for(j = 0; j < M; j ++)
            {
                hm[cur ^ 1].init();
                if(g[i][j] != '#') dp(i, j, 0, cur);
                if(g[i][j] != 'o') dp(i, j, 1, cur);
                cur ^= 1;
            }
        for(i = 0; i < hm[cur].size; i ++)
        {
            int max = 0;
            decode(code, M, hm[cur].st[i]);
            for(j = 0; j < M; j ++) max = std::max(max, code[j]);
            if(max > 1) continue;
            ans += hm[cur].dp[i], k = i;
        }
        printf("%d\n", ans);
        if(ans != 0) print(k);
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            init();
            solve();
            printf("\n");
        }
        return 0;    
    }
  • 相关阅读:
    阿里P8聊并发编程:线程中断和终止
    浅谈Java中的锁:Synchronized、重入锁、读写锁
    史上最全Java面试题!进程,线程相关部分下篇(带全部答案)
    @史上最全Java面试题!关于volatile关键字篇(带全部答案)
    @史上最全Java面试题!进程,线程相关部分上篇(带全部答案)
    一道号称“史上最难”java面试题引发的线程安全思考,掌握了吗?
    stopWatch
    mysql语句及执行计划
    Awr
    文件下载
  • 原文地址:https://www.cnblogs.com/staginner/p/2688847.html
Copyright © 2011-2022 走看看