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