去年写这一题不知道BFS要避免重复访问相同的状态,一直MLE。。拖了一年开始写了。
很明显的状态压缩,used[x][y][key]用来标记表示在[x,y]点处拿到key的宝物的状态,key用二进制数表示是否取得了某一个宝物,例如1001表示取得了第一个和第四个宝物。
然后这次因为访问的状态表急错了也MLE了几次。。==
#include<iostream> #include<stdio.h> #include<cstdio> #include<stdlib.h> #include<vector> #include<string> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<queue> #include <ctype.h> using namespace std; int N; int M; int K; int mp[110][110]; int used[110][110][1<<4]; //int d[110][110][1<<4]; int ans; int dx[]={0,-1,0,1}; int dy[]={-1,0,1,0}; struct node { public: int x; int y; int key; int step; node(){} node(int xx,int yy,int k,int s) { x=xx; y=yy; key=k; step=s; } }; pair<int,int> st; pair<int,int> prec[4]; queue<node>q; void bfs() { while(!q.empty()) q.pop(); int s=0; if(mp[st.first][st.second]>=2) { s=(1<<mp[st.first][st.second])-2; } node a=node(st.first,st.second,s,0); q.push(a); while(!q.empty()) { node tmp=q.front(); q.pop(); int x=tmp.x; int y=tmp.y; int key=tmp.key; int step=tmp.step; used[x][y][key]=false; // cout<<x<<" "<<y<<" "<<key<<" "<<step<<endl; if(key==((1<<K)-1)) { ans=step;//need to get min? return; } for(int i=0;i<4;i++) { if(x+dx[i]>=1&&x+dx[i]<=N&&y+dy[i]>=1&&y+dy[i]<=M&&mp[x+dx[i]][y+dy[i]]>=1)//used[x+dx[i]][y+dy[i]]&& 该点是否走过要根据下面key的状态判断,我都不造这里USED只写了两维怎么还能进if的 { if(mp[x+dx[i]][y+dy[i]]>=2&&mp[x+dx[i]][y+dy[i]]<=(K+1)) { int new_k=mp[x+dx[i]][y+dy[i]]-2;//这里米有考虑两个宝物在同一个格子里的case // if((key&(1<<new_k))==0)//used在下面才判定,所以这里不能有if // { if(used[x+dx[i]][y+dy[i]][key|(1<<new_k)]==false) continue; node tmp2=node(x+dx[i],y+dy[i],key|(1<<new_k),step+1); q.push(tmp2); used[x+dx[i]][y+dy[i]][key|(1<<new_k)]=false;//一定要标记访问,否则会MLE // } } else { if(used[x+dx[i]][y+dy[i]][key]==false) continue; node tmp2=node(x+dx[i],y+dy[i],key,step+1); q.push(tmp2); used[x+dx[i]][y+dy[i]][key]=false; } } } } } int main() { freopen("input.txt","r",stdin); // freopen("data.txt","r",stdin); //freopen("out1.txt","w",stdout); while(true) { scanf("%d %d",&N,&M); memset(used,true,sizeof(used)); memset(mp,true,sizeof(mp)); ans=-1; if(N==0&&M==0) break; else { for(int i=1;i<=N;i++) { for(int j=1;j<=M;j++) { char str; cin>>str; if(str=='#') mp[i][j]=0; else if(str=='.') mp[i][j]=1; else if(str=='@') { mp[i][j]=0; st.first=i; st.second=j; } } } } scanf("%d",&K); for(int i=0;i<K;i++) { int x,y=0; scanf("%d %d",&x,&y); mp[x][y]=i+2; prec[i]=make_pair(x,y); } bfs(); printf("%d\n",ans); // puts(" "); } return 0; }