这道题是09年上海区域赛的A题,虽然很水,但是不能直接爆搜,直接爆搜要T。于是我们看到题目的要求是说当操作的步数大于3的时候就输出more,那么我们可以从终态枚举进行了三次操作所能达到的所有状态,这个是用广搜应该还是很好写的。我们直接使用vis数组就完全可以胜任这个记录了,没有必要用任何的结构体。
我们在枚举操作的时候,因为我们仅仅只有32条边,我们直接手工输入这32条边,然后在广搜的过程中直接枚举边进行操作就行了,但是注意的一点是,题目中的要求是说这条边的两个端点的灯的状态必须是不一样的,才能进行操作,我在这个地方差点wa到死,好伤心啊!最后使用vis数组判断,进行相应的输出就可以了。
下面贴上我的代码(代码应该还是比较简洁清晰的):
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
using namespace std;
int a[32]={1,3,2,1,10,2, 4, 1,3, 9, 9, 11, 6,14,6, 8, 5,13,5, 7, 13,15,5,7, 2,4,12,10,3,1,11,9};
int b[32]={2,4,4,3,12,10,12,9,11,11,10,12, 8,16,14,16,7,15,13,15,14,16,6,8, 6,8,16,14,7,5,15,13};
int vis[1000000];
int getState(int *st)
{
int ans=0;
for(int i=0;i<16;i++)
{
if(st[i])
{
ans|=(1<<i);
}
}
return ans;
}
void bfs(int s)
{
vis[s]=0;
queue<int> q;
q.push(s);
while(!q.empty())
{
int fr=q.front();
q.pop();
if(vis[fr]>=3)
continue;
for(int i=0;i<32;i++)
{
int temp=fr;
int j1=fr&(1<<(a[i]-1));
int j2=fr&(1<<(b[i]-1));
if(j1==j2)
continue;
temp^=(1<<(a[i]-1));
temp^=(1<<(b[i]-1));
if(vis[temp]==-1)
{
vis[temp]=vis[fr]+1;
if(vis[temp]<3)
q.push(temp);
}
}
}
}
int main()
{
int st[16]={0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1};
int s=getState(st);
memset(vis,-1,sizeof(vis));
bfs(s);
int T;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
for(int i=0;i<16;i++)
scanf("%d",&st[i]);
s=getState(st);
printf("Case #%d: ",cas);
if(vis[s]==-1||vis[s]>3)
printf("more\n");
else
printf("%d\n",vis[s]);
}
return 0;
}