3 3 ABA CBC 3 BAA CCB 3 BBB BAB
Case #1: 3 Case #2: 3 Case #3: 2
#include <cstdio> #include <cstring> #include <queue> using namespace std; struct NODE { int val; int step; }; bool vis[1 << 16]; //标记各位置是否达到目标色 char s[20]; int n; int BFS() { queue<NODE> q; NODE st, cur, next; memset(vis, false, sizeof(vis)); vis[0] = true; st.val = 0; st.step = 0; q.push(st); while(!q.empty()) { cur = q.front(); q.pop(); //各位都为1则涂色完成 if(cur.val == (1 << 2 * n) - 1) return cur.step; for(int i = 0; i < 2 * n; i++) { //如果当前位置已经涂色,则不作为拓展原点 if((1 << i) & cur.val) continue; next = cur; next.step ++; int tmp = 0; //单行向右扩展 int nn = i < n ? n : 2 * n; for(int j = i; j < nn; j++) { //若该点已经涂色则退出循环 if((1 << j) & cur.val) break; //若该点未涂色且颜色和目标色相同则上色 if(s[j] == s[i]) tmp = tmp | (1 << j); } //单行向左扩展 nn = i < n ? 0 : n; for(int j = i - 1; j >= nn; j--) { if((1 << j) & cur.val) break; if(s[j] == s[i]) tmp = tmp | (1 << j); } //将所有状态分离,若出现新的状态则加入队列 for(int j = tmp; j; j = tmp & (j - 1)) { int val = cur.val | j; if(!vis[val]) { vis[val] = true; next.val = val; q.push(next); } } //双行扩展通过第一行来得到第二行,若当前对应 //的第二行的位置已经涂色,则该列不作为拓展原点 if(i >= n || (cur.val & (1 << i + n))) continue; tmp = 0; for(int j = i; j < n; j++) { if(((1 << j) & cur.val) || ((1 << (j + n)) & cur.val)) break; if(s[j] == s[i]) tmp |= (1 << j); if(s[j + n] == s[i]) tmp |= (1 << (j + n)); } for(int j = i - 1; j >= 0; j--) { if(((1 << j) & cur.val) || ((1 << (j + n)) & cur.val)) break; if(s[j] == s[i]) tmp |= (1 << j); if(s[j + n] == s[i]) tmp |= (1 << (j + n)); } for(int j = tmp; j; j = tmp & (j - 1)) { int val = cur.val | j; if(!vis[val]) { vis[val] = true; next.val = val; q.push(next); } } } } return 0; } int main() { int T; scanf("%d", &T); for(int ca = 1; ca <= T; ca++) { scanf("%d", &n); scanf("%s %s", s, s + n); //将两行读做一行 printf("Case #%d: %d\n", ca, BFS()); } }
HDU 4012 Paint on a Wall (状态压缩+BFS)
原文地址:http://blog.csdn.net/tc_to_top/article/details/43701909