ZOJ 3531 模拟+BFS

View Code
  1 #include <cstdio>

  2 #include <cstdlib>

  3 #include <cstring>

  4 #include <algorithm>

  5 #include <iostream>

  6 #include <queue>

  7 #include <set>

  8 #include <stack>

  9 #include <bitset>

 10 

 11 using namespace std;

 12 

 13 #define print(x) cout<<x<<endl

 14 #define input(x) cin>>x

 15 #define SIZE 12

 16 #define elif else if

 17 #define INF 1<<30

 18 #define MOD 100000007

 19 

 20 struct point

 21 {

 22     int x,y;

 23     point(){x=y=-1;}

 24     point(int i_x,int i_y)

 25     {

 26         x=i_x;y=i_y;

 27     }

 28     friend bool operator == (const point& a,const point& b)

 29     {

 30         return a.x==b.x && a.y==b.y;

 31     }

 32     

 33     friend bool operator != (const point& a,const point& b)

 34     {

 35         return !(a.x==b.x && a.y==b.y);

 36     }

 37 };

 38 

 39 char g[SIZE][SIZE];

 40 point piece[SIZE];

 41 int m,n,ind;

 42 const int mx[]={0,1,0,-1};

 43 const int my[]={-1,0,1,0};

 44 bitset<MOD> hash;

 45 //TLE:

 46 //Hash is faster than Set

 47 

 48 

 49 int makeStatus(const point& pawn,const point& mir,const point& knight,int knightDir,int getMem)

 50 {

 51     int res=0;

 52     res|=getMem;

 53     res<<=4;res|=knight.x;

 54     res<<=4;res|=knight.y;

 55     res<<=2;res|=knightDir;

 56     res<<=4;res|=mir.x;

 57     res<<=4;res|=mir.y;

 58     res<<=4;res|=pawn.x;

 59     res<<=4;res|=pawn.y;

 60     return res;

 61 }

 62 

 63 bool inMap(const point& p)

 64 {

 65     if(p.x>=0 && p.x<m && p.y>=0 && p.y<n)

 66     {

 67         if(g[p.y][p.x]=='R') return false;

 68         else return true;

 69     }

 70     return false;

 71 }

 72 

 73 struct node

 74 {

 75     unsigned int status;

 76     int step;

 77 

 78     node(){}

 79     node(int i_status,int i_step)

 80     {

 81         status=i_status;

 82         step=i_step;

 83     }

 84     int OK()//Drei Status caused WA

 85     {

 86         int st=status;

 87         int res=status>>26;

 88         int a,b;

 89         a=b=(1<<4)-1;

 90         b&=st;st>>=4;

 91         a&=st;st>>=4;

 92         point pawn=point(a,b);

 93         a=b=(1<<4)-1;

 94         b&=st;st>>=4;

 95         a&=st;st>>=4;

 96         point mirPawn=point(a,b);

 97         int ok=(1<<ind)-1;

 98         if(ind==0) ok=0;

 99         if(g[pawn.y][pawn.x]=='E' && g[mirPawn.y][mirPawn.x]=='E')

100         {

101             if(res==ok) return true;

102             else return -1;

103         }

104         else return false;

105     }

106     bool move(int dir)

107     {

108         step++;

109         int a,b;

110         a=b=(1<<4)-1;

111         b&=status;status>>=4;

112         a&=status;status>>=4;

113         point pawn=point(a,b);

114         

115         a=b=(1<<4)-1;

116         b&=status;status>>=4;

117         a&=status;status>>=4;

118         point mirPawn=point(a,b);

119 

120         a=(1<<2)-1;

121         a&=status;

122         int knightDir=a;

123         status>>=2;

124 

125         a=b=(1<<4)-1;

126         b&=status;status>>=4;

127         a&=status;status>>=4;

128         point knight=point(a,b);

129 

130         int gain=status;

131 

132         point nextPawn=pawn;

133         nextPawn.x+=mx[dir];

134         nextPawn.y+=my[dir];

135         if(inMap(nextPawn))

136         {

137             if(nextPawn==knight || nextPawn==mirPawn) return false;

138             pawn=nextPawn;

139         }

140         else return false;

141 

142         point nextMirPawn=mirPawn;

143         nextMirPawn.x+=mx[(dir+2)%4];

144         nextMirPawn.y+=my[(dir+2)%4];

145         if(inMap(nextMirPawn) && nextMirPawn!=knight && nextMirPawn!=pawn)

146         {

147             mirPawn=nextMirPawn;

148         }

149         point nextKnight=knight;

150         nextKnight.x+=mx[knightDir];

151         nextKnight.y+=my[knightDir];

152         if(inMap(nextKnight)) knight=nextKnight;

153         else knightDir=(knightDir+2)%4;

154 

155         if(g[pawn.y][pawn.x]=='E' && g[mirPawn.y][mirPawn.x]=='E')

156         {

157             status=makeStatus(pawn,mirPawn,knight,knightDir,gain);

158         }

159         else

160         {

161             if(knight==pawn || knight==mirPawn) return false;

162             for(int i=0;i<ind;i++)

163             {

164                 if(pawn==piece[i]) gain|=(1<<i);//Only Alice can attach to the Memory Piece WA

165             }

166             status=makeStatus(pawn,mirPawn,knight,knightDir,gain);

167         }

168         return true;

169     }

170     

171     void printinfo()

172     {

173         char tg[SIZE][SIZE];

174         memcpy(tg,g,sizeof(g));

175         print("INFO:"<<step);

176         int st=status;

177         int a,b;

178         a=b=(1<<4)-1;

179         b&=status;status>>=4;

180         a&=status;status>>=4;

181         point pawn=point(a,b);

182         tg[b][a]='A';

183         

184         a=b=(1<<4)-1;

185         b&=status;status>>=4;

186         a&=status;status>>=4;

187         point mirPawn=point(a,b);

188         tg[b][a]='B';

189 

190         a=(1<<2)-1;

191         a&=status;

192         int knightDir=a;

193         status>>=2;

194         printf("KnightDir:%d\n",knightDir);

195 

196         a=b=(1<<4)-1;

197         b&=status;status>>=4;

198         a&=status;status>>=4;

199         point knight=point(a,b);

200         tg[b][a]='K';

201         int gain=status;

202         printf("Gain:%d\n",gain);

203         status=st;

204         for(int i=0;i<ind;i++)

205         {

206 

207             if(!(gain & (1<<i)))

208             {

209                 tg[piece[i].y][piece[i].x]='M';

210             }

211         }

212         for(int i=0;i<n;i++) print(tg[i]);

213         print("-------------------");

214     }

215 };

216 

217 

218 inline int char2Dir(char x)

219 {

220     switch(x)

221     {

222         case 'N':return 0;break;

223         case 'E':return 1;break;

224         case 'S':return 2;break;

225         case 'W':return 3;break;

226     }

227     return -1;

228 }

229 

230 

231 int bfs(int i_status)

232 {

233     queue<node> q;

234     int ans=INF;

235     hash.reset();

236     q.push(node(i_status,0));

237     while(!q.empty())

238     {

239         node now=q.front();

240         q.pop();

241         //now.printinfo();

242         if(hash[now.status%MOD]) continue;

243         else hash[now.status%MOD]=1;

244         int ok=now.OK();

245         if(ok==1)

246         {

247             ans=min(ans,now.step);

248             break;

249         }

250         elif(ok==-1) continue;

251         for(int i=0;i<4;i++)

252         {

253             node next=now;

254             if(next.move(i)) q.push(next);

255         }

256     }

257     return ans;

258 }

259 

260 int main()

261 {

262     //freopen("input.txt","r",stdin);

263     char cmd[4];

264     while(input(n>>m))

265     {

266         for(int i=0;i<n;i++) scanf("%s",g[i]);

267 

268         scanf("%s",cmd);

269         ind=0;

270         point pawn,mirPawn;

271         point knight;

272         for(int i=0;i<n;i++)

273         {

274             for(int j=0;j<m;j++)

275             {

276                 if(g[i][j]=='A') pawn=point(j,i);

277                 elif(g[i][j]=='B') mirPawn=point(j,i);

278                 elif(g[i][j]=='K') knight=point(j,i);

279                 elif(g[i][j]=='M') piece[ind++]=point(j,i);

280 

281                 if(g[i][j]!='E' && g[i][j]!='*' && g[i][j]!='R')

282                 {

283                     g[i][j]='*';

284                 }

285             }

286         }

287         int status=makeStatus(pawn,mirPawn,knight,char2Dir(*cmd),0);

288         int ans=bfs(status);

289         if(ans>=INF) ans=-1;

290         print(ans);

291     }

292     return 0;

293 }

你可能感兴趣的:(bfs)