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 }

posted on 2012-04-17 21:14  Wizmann  阅读(191)  评论(0)    收藏  举报

导航