zoukankan      html  css  js  c++  java
  • HDU 3633 Black and white

    HDU_3633

        这个题目确实比较复杂,具体的思路还是参考胡浩的解题报告吧:

    View Code // My code
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define HASH 100007
    #define MAXD 100010
    #define INF 0x3f3f3f3f
    int N, M, pre[65][MAXD], a[10][10];
    char op[65][MAXD], g[10][10];
    struct HashMap
    {
        int head[HASH], size, next[MAXD], st[MAXD], dif[MAXD], col[MAXD], dp[MAXD];
        void init()
        {
            memset(head, -1, sizeof(head)), size = 0;
        }
        void push(int _st, int _dif, int _col, int _dp, int id, int p, char ch)
        {
            int i, h = ((_st << 6) + _col + 2000 + _dif) % HASH;
            for(i = head[h]; i != -1; i = next[i])
                if(st[i] == _st && dif[i] == _dif && col[i] == _col)
                {
                    dp[i] += _dp;
                    return ;
                }
            st[size] = _st, dif[size] = _dif, col[size] = _col, dp[size] = _dp;
            pre[id][size] = p, op[id][size] = ch;
            next[size] = head[h], head[h] = size ++;
        }
    }hm[2];
    void init()
    {
        int i, j;
        scanf("%d%d", &N, &M);
        for(i = 0; i < N; i ++) scanf("%s", g[i]);
        for(i = 0; i < N; i ++)
            for(j = 0; j < M; j ++) scanf("%d", &a[i][j]);
    }
    int code[10], h[10];
    inline void decode(int *code, int m, int st)
    {
        for(int i = m - 1; i >= 0; i --) code[i] = st & 7, st >>= 3;    
    }
    inline 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 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 = i && j ? (col >> M) == c : 0;
            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 t, s1 = 0, s2 = 0;
                for(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(l && u)
            {
                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(l && !u) code[j] = code[j - 1];
            else if(!l && !u) 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), hm[cur].dif[k] + (c ? a[i][j] : -a[i][j]), col, hm[cur].dp[k], i * M + j, k, c ? 'x' : '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 ++) printf("%s\n", g[i]);
    }
    void solve()
    {
        int i, j, k, cur = 0, ans = 0, min = INF;
        hm[0].init();
        hm[0].push(0, 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] != 'x') 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 s1 = 0;
            memset(h, 0, sizeof(h));
            decode(code, M, hm[cur].st[i]);
            for(j = 0; j < M; j ++) if(!h[code[j]]) ++ s1, h[code[j]] = 1;
            if(s1 <= 2)
            {
                if(std::abs(hm[cur].dif[i]) < min)
                    min = std::abs(hm[cur].dif[i]), ans = hm[cur].dp[i], k = i;
                else if(std::abs(hm[cur].dif[i]) == min)
                    ans += hm[cur].dp[i];
            }
        }
        if(min == INF) printf("0 0\n");
        else
        {
            printf("%d %d\n", min, ans);
            print(k);
        }
    }
    int main()
    {
        int t, tt;
        scanf("%d", &t);
        for(tt = 1; tt <= t; tt ++)
        {
            init();
            printf("Case %d: ", tt);
            solve();    
            printf("\n");
        }
        return 0;    
    }
    View Code // by NotOnlySuccess
    //by NotOnlySuccess
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const char Black = 'x';
    const char White = 'o';
    const int Hsize = 100007;
    int PRE[65][Hsize];
    char DRAW[65][Hsize];
    int cur;
    
    struct HashMap {
        int HashChart[Hsize] , sz;
        int MSK[Hsize];
        int DP[Hsize];
        int COL[Hsize];
        int DIFF[Hsize];
        int next[Hsize];
        void clear() {
            sz = 0;
            memset(HashChart, -1, sizeof( HashChart ));
        }
        inline void push(int msk, int col, int dp, int diff, int pre, char draw) {
            int x = ( msk * 19 + col * 1023 + ( 2000 + diff ) ) % Hsize;
            for ( int it = HashChart[x] ; it != -1 ; it = next[it] ) {
                if ( MSK[it] == msk && COL[it] == col && DIFF[it] == diff ) {
                    DP[it] += dp;
                    return;
                }
            }
            PRE[cur][sz] = pre;
            DRAW[cur][sz] = draw;
    
            DIFF[sz] = diff;
            MSK[sz] = msk;
            DP[sz] = dp;
            COL[sz] = col;
            next[sz] = HashChart[x];
            HashChart[x] = sz ++;
        }
    } HM[2] , *src , *des;
    
    int n , m;
    char maze[9][9];
    int dig[8][8];
    int Bin[8];
    int code[8];
    inline void decode(int *code, int msk) {
        for ( int it = 0 ; it < m ; it ++ ) {
            code[it] = msk & 7;
            msk >>= 3;
        }
    }
    inline int encode(int *code) {
        int ret = 0 , cnt = 0;
        memset(Bin, -1, sizeof( Bin ));
        for ( int it = m - 1 ; it >= 0 ; it -- ) {
            if ( Bin[code[it]] < 0 ) Bin[code[it]] = cnt ++;
            ret <<= 3;
            ret |= Bin[code[it]];
        }
        return ret;
    }
    
    void DP(int i, int j, int paint, int msk, int col, int dp, int diff, int k) {
    
        int up = i ? ( col >> j & 1 ) == paint : 0;
        int left = j ? ( col >> ( j - 1 ) & 1 ) == paint : 0;
    
        if ( up && left && ( col >> m & 1 ) == paint ) return;
        if ( i == n - 1 && j == m - 1 && !up && !left && ( col >> m & 1 ) == paint ) return;
    
        decode(code, msk);
        if ( i && !up ) {
            int sc = 0 , s = 0;
            for ( int it = 0 ; it < m ; it ++ ) {
                if ( code[it] == code[j] ) s ++;
                if ( ( col >> it & 1 ) != paint ) sc ++;
            }
            if ( s == 1 ) {
                if ( sc > 1 ) return;
                if ( i < n - 1 || j < m - 2 ) return;
        //        if ( j == m - 2 && maze[i][j + 1] != '.' && ( maze[i][j + 1] == 'x' ) != paint ) return;
            }
        }
    
        if ( up && left ) {
            if ( code[j] != code[j - 1] ) {
                for ( int it = 0 , x = code[j] ; it < m ; it ++ ) {
                    if ( code[it] == x ) code[it] = code[j - 1];
                }
            }
        } else if ( !up && !left ) code[j] = 7;
        else if ( !up && left ) code[j] = code[j - 1];
    
        if ( col >> j & 1 ) col |= ( 1 << m );
        else col &= ~( 1 << m );
        if ( paint ) col |= ( 1 << j );
        else col &= ~( 1 << j );
        des->push(encode(code), col, dp, diff, k, paint ? 'x' : 'o');
    }
    bool check(int msk) {
        decode(code, msk);
        int maxcode = 0;
        for ( int it = 0 ; it < m ; it ++ ) {
            if ( maxcode < code[it] ) maxcode = code[it];
        }
        if ( maxcode > 1 ) return false;
        return true;
    }
    void output() {
        int ret = 0;
        int y;
        int mindiff = 0x7fffffff;
        for ( int k = 0 ; k < src->sz ; k ++ ) {
            if ( check(src->MSK[k]) ) {
                if ( abs(src->DIFF[k]) < mindiff ) {
                    mindiff = abs(src->DIFF[k]);
                    ret = src->DP[k];
                    y = k;
                } else if ( abs(src->DIFF[k]) == mindiff ) {
                    ret += src->DP[k];
                    y = k;
                }
            }
        }
        if ( ret == 0 ) {
            puts("0 0");
        } else {
            printf("%d %d\n", mindiff, ret);
            int x = cur;
            while ( x ) {
                maze[( x - 1 ) / m][( x - 1 ) % m] = DRAW[x][y];
                y = PRE[x][y];
                x --;
            }
            for ( int i = 0 ; i < n ; i ++ ) {
                for ( int j = 0 ; j < m ; j ++ ) {
                    printf("%c", maze[i][j]);
                }
                puts("");
            }
        }
        puts("");
    }
    void work() {
        src = HM;
        des = HM + 1;
        cur = 0;
        src->clear();
        src->push(0, 0, 1, 0, -1, '*');
        for ( int i = 0 ; i < n ; i ++ ) {
            for ( int j = 0 ; j < m ; j ++ ) {
                cur ++;
                printf(":: %d %d %d\n", i, j, src->sz);
                des->clear();
                for ( int k = 0 ; k < src->sz ; k ++ ) {
                    if ( maze[i][j] != Black ) DP(i, j, 0, src->MSK[k], src->COL[k], src->DP[k], src->DIFF[k] - dig[i][j], k);
                    if ( maze[i][j] != White ) DP(i, j, 1, src->MSK[k], src->COL[k], src->DP[k], src->DIFF[k] + dig[i][j], k);
                }
                swap(src, des);
            }
        }
        output();
    }
    void readdata() {
        scanf("%d%d", &n, &m);
        for ( int i = 0 ; i < n ; i ++ ) {
            scanf("%s", maze[i]);
        }
        for ( int i = 0 ; i < n ; i ++ ) {
            for ( int j = 0 ; j < m ; j ++ ) {
                scanf("%d", &dig[i][j]);
            }
        }
    }
    int main() {
        //freopen("B.in","r",stdin);
        //freopen("BB.out","w",stdout);
        int T , cas = 1;
        scanf("%d", &T);
        while ( T -- ) {
            printf("Case %d: ",cas++);
            readdata();
            work();
        }
        return 0;
    }
  • 相关阅读:
    Maven常用命令
    SpringBoot实战(十三)之缓存
    python3对数据库的基本操作
    Microsoft visual c++ 14.0 is required问题
    python3之安装mysql问题
    如何将pip更新到最新版
    Java特性之继承的应用
    人人开源之代码生成器(renren-generator)
    《你凭什么做好互联网》之思维导图归纳
    GETOBJECTOPTIONS
  • 原文地址:https://www.cnblogs.com/staginner/p/2688634.html
Copyright © 2011-2022 走看看