您的位置:首页 > 其它

HDU 3633 Black and white

2012-09-17 13:58 309 查看
HDU_3633

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

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: