Description
经过谢老师n次的教导,pige终于觉悟了——过于腐败是不对的。但是pige自身却无法改变自己,于是他找到了你,请求你的帮助。
pige的内心可以看成是5*5个分区组成,每个分区都可以决定的的去向,0表示继续爱好腐败,1表示改正这个不良的习惯。只有当25个分区都为1时,pige才会改正腐败这个不良习惯。你有一根神奇的魔法棒,可以使点中的分区以及这个分区上下左右改变(1变0,0变1)。这根神奇的魔法棒只能使用6次了,请问你最少使用多少次才可以救醒这pige。(使用超过6次则输出-1,表示pige已经无药可救了)。(因为pige实在太顽固不化,所以你要救醒他n次,但每次都有会获得由谢老师送的一根新的魔法棒,不过之前那根会消失)。
Input
第一行有一个正整数n,代表数据中共有n组数据。
以下若干行数据分为n组,每组数据有5行,每行5个字符。每组数据描述了25个分区的初始状态。各组数据间用一个空行分隔。
Output
输出数据一共有n行,每行有一个小于等于6的整数,它表示对于输入数据中对应的每组数据最少需要几步才能将救醒pige。
对于一个数据,如果无法在规定的条件救醒pige,请输出“-1”。
Hint
30%,n <= 5;
100%,n <= 500。
Analysis
好久好久好久好久好久以前的位运算搜索
位运算极其重要,要好好学习
—来自AJ
然后我就放到了今天(┬_┬)
咳咳,严肃严肃
从全为1的起点开始bfs,直接用桶判重+步数记录
然后对于每个答案
O(1)
出解
深度只有6,随便搞都可以
数组要开short不然会MLE
Code
#include <stdio.h>
#include <string.h>
#include <queue>
#define lim (1<<25)-1
#define n 5
using namespace std;
queue<int>q;
short ans[lim+1];
char s[5];
int get(int x,int y)
{
return (x-1)*n+y-1;
}
void bfs()
{
q.push(lim);
ans[lim]=1;
while (!q.empty())
{
int now=q.front();q.pop();
if (ans[now]+1<=7)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
int tmp=now;
tmp^=1<<get(i,j);
if (i>1)
tmp^=1<<get(i-1,j);
if (i<n)
tmp^=1<<get(i+1,j);
if (j>1)
tmp^=1<<get(i,j-1);
if (j<n)
tmp^=1<<get(i,j+1);
if (!ans[tmp])
{
ans[tmp]=ans[now]+1;
q.push(tmp);
}
}
}
}
int main()
{
bfs();
int t;
scanf("%d",&t);
for (int i=1;i<=t;i++)
{
int st=0;
for (int i=1;i<=n;i++)
{
scanf("%s",s);
for (int j=1;j<=n;j++)
st|=(s[j-1]-'0')<<get(i,j);
}
printf("%d\n",ans[st]-1);
}
return 0;
}