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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
针对性很强,不懂3633意思勿下 有时会出现无法连接服务,重开一般就行 有什么需要改进的地方,多多建议哦,传达给您的上家就行 运行环境 需要.net 4支持。 怎么开始使用本软件 首先向上家购买注册码,注意 注册信息的QQ是3633网站的登录名,而且有绑定机器的哦~ 然后打开软件,如果有什么警告提示,直接继续或continue。 打开软件后,填入网站登录密码,设置预设方案,点击打开登录页,点击登录 点击任务中心,点击设置绑定。(自动开始功能已经关闭) 直接点击设置绑定,可以实现一键登录自动开始,但需先设置预设方案。 字体可以大点或小点吗? 鼠标点下页面,CTRL+滚动条,就可以放大缩小 可以自定义条件吗? 可以,单条件:非白号 仅白号 非秒单 仅秒单 非手机 仅手机 非福建 或非地区 非其它{地区名1,地区名2} 基5 基3 基6 三心 一心 四心 一钻 二钻 一冠 二冠 单链接 多链接 非实名 仅实名 加1 不加 不聊 要聊 组合条件:三心非白号非秒单 基5四心非手机非福建单链接 建议用基础佣金来限定,不要用非秒单来限定。 选择预设方案,如果没有就手输,输完,点设置条件,查看是否能正确设置 加QQ无反应 请将本软件添加为360或其它安全软件的信任软件。 该旺旺低于要求的最低信益 接手的单有时会超出设置的条件范围,绑定框点关闭,到已接任务里去查看,然后绑定。这种情况有时是小号前后多了空格引起的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值