HDU_4012
这个题目可以用BFS加一些剪枝搜过去。
首先状态可以用0、1表示该位是否涂上了正确的颜色,这样状态总数不超过2^16。接下来就要枚举每次涂的矩形的位置以及颜色了,在枚举的时候要加一些剪枝。
涂的矩形无非有两种情况,要么是一行,要么是两行。
如果是一行的矩形,那么两端的正确颜色要一致,而且两端都未涂上正确颜色,否则这个矩形是没有必要涂的。
如果是两行的矩形,那么左端的上下两个位置中至少应有一个是未涂上正确颜色的,而且这个矩形所涂的颜色应为这两个位置中尚未涂上正确颜色的位置的正确颜色,否则这个矩形是没有必要涂的。
除此之外还有其他一些剪枝。
#include<stdio.h> #include<string.h> #define MAXD 70000 #define MAXN 20 #define HASH 100007 int N; char b[MAXN]; struct Hashmap { int head[HASH], size, next[MAXD], state[MAXD], step[MAXD]; void init() { memset(head, -1, sizeof(head)); size = 0; } void push(int st, int k) { int i, h = st % HASH; for(i = head[h]; i != -1; i = next[i]) if(state[i] == st) return ; step[size] = k, state[size] = st; next[size] = head[h], head[h] = size ++; } }hm; void init() { int i; scanf("%d", &N); scanf("%s", b); scanf("%s", b + N); } int complete(int st) { return st == (1 << (N << 1)) - 1; } int newnode(int flag, int y1, int y2, char ch, int st) { int i, j; if(flag != 1) { for(j = y1; j <= y2; j ++) { if(b[j] == ch) st |= 1 << j; else if(st & 1 << j) st -= 1 << j; } } if(flag != 0) { for(j = y1; j <= y2; j ++) { if(b[j + N] == ch) st |= 1 << (j + N); else if(st & 1 << (j + N)) st -= 1 << (j + N); } } return st; } void solve() { int i, j, k, x, y, st, state; hm.init(); hm.push(0, 0); for(k = 0; k < hm.size; k ++) { if(complete(state = hm.state[k])) break; for(j = 0; j < N; j ++) { if((state & 1 << j) == 0) { for(y = j; y < N; y ++) { if(b[j] == b[y] && (state & 1 << y) == 0) { st = newnode(0, j, y, b[j], state); hm.push(st, hm.step[k] + 1); } if((b[j] == b[y] && (state & 1 << y) == 0) || (b[j] == b[y + N] && (state & 1 << (y + N)) == 0)) { st = newnode(-1, j, y, b[j], state); hm.push(st, hm.step[k] + 1); } } } if((state & 1 << (j + N)) == 0) { for(y = j; y < N; y ++) { if(b[j + N] == b[y + N] && (state & 1 << (y + N)) == 0) { st = newnode(1, j, y, b[j + N], state); hm.push(st, hm.step[k] + 1); } if((b[j + N] == b[y] && (state & 1 << y) == 0) || (b[j + N] == b[y + N] && (state & 1 << (y + N)) == 0)) { st = newnode(-1, j, y, b[j + N], state); hm.push(st, hm.step[k] + 1); } } } } } printf("%d\n", hm.step[k]); } int main() { int t, tt; scanf("%d", &t); for(tt = 0; tt < t; tt ++) { init(); printf("Case #%d: ", tt + 1); solve(); } return 0; }