这道题是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; }