HDU 3633 Black and white
2012-09-17 13:58
309 查看
HDU_3633
这个题目确实比较复杂,具体的思路还是参考胡浩的解题报告吧:
View Code // by NotOnlySuccess
这个题目确实比较复杂,具体的思路还是参考胡浩的解题报告吧:
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; }
相关文章推荐
- HDU 3633 Black and white(插头DP)
- HDU - 5113 Black And White 搜索+剪枝 ( 2014ACM/ICPC亚洲区北京站-重现赛(感谢北师和上交))
- HDU 5583 Kingdom of Black and White(依旧是暴力)——2015ACM/ICPC亚洲区上海站
- hdu 5583 Kingdom of Black and White
- HDU 3911 Black And White 分段树 题解
- HDU 3911 Black And White(线段树区间合并+lazy操作)
- hdu 5113 Black And White
- hdu 3911 Black And White
- HDU 5113 Black And White(2014亚洲区北京站现场赛)
- hdu 3911 Black And White 线段树区间合并
- HDU 3911 Black And White
- hdu 5113 Black And White(dfs+剪枝)
- HDU 3911 Black And White 线段树
- HDU 5583 Kingdom of Black and White(暴力)
- hdu 3911 Black and White 线段树维护01序列
- hdu 3911 Black And White
- hdu 3911 Black And White
- hdu 3911 Black And White
- HDU 5113 Black And White(深搜+剪枝)
- hdu 5113: Black And White(dfs+强剪枝)