题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=361
BFS。。ZOJ的数据相对poj水了点,直接BFS。就可以过了、这题关键是判重,把蛇头坐标和蛇身相对坐标表示出来。。在获取蛇身的相对坐标时搞错了。导致错了N次。
计算蛇身时,要把蛇头去掉。也就是l-1,= =!
对于poj的数据,我用的a*过的。。稍微加了一下优化。。评估函数为当前步数加上蛇头到(1,1)的至少应该走的步数。 (单独) 蛇头到(1,1)的至少应走的步数的计算,也就是不计算蛇身的位置。那么直接BFS就可以了。
如果还加上蛇身。效率应该更快。但是我这样写简便一点。
下面是没优化的代码:
#include<cstdio> #include<queue> #include<cstring> #include<cstdlib> using namespace std; const int maxn =21; int n,m,l,find,ans,move; bool map[maxn][maxn]; int dx[]={1,-1,0,0}; int dy[]={0,0,1,-1}; bool vis[maxn][maxn][1<<14]; bool check(int x,int y){ return x>=1&&x<=n&&y>=1&&y<=m; } struct node{ int head[2],tail[2]; bool map[maxn][maxn]; int step,val; }s_pos; void bfs(){ memset(vis,false,sizeof(vis)); queue<node > q; q.push(s_pos); vis[s_pos.head[0]][s_pos.head[1]][ s_pos.val] =true; while(!q.empty()){ node now = q.front(); q.pop(); if(now.head[0]==1&&now.head[1]==1){ find=1; ans=now.step; return ; } for(int i=0;i<4;i++){ node next = now; next.step+=1; int x=now.head[0]+dx[i]; int y=now.head[1]+dy[i]; if(check(x,y)){ if(next.map[x][y]) continue; next.head[0]=x; next.head[1]=y; next.map[x][y]=true; next.map[now.tail[0]][now.tail[1]]=false; int t= next.val&3; next.tail[0]=now.tail[0]+dx[t]; next.tail[1]=now.tail[1]+dy[t]; next.val=next.val>>2; int sum=i<<move; next.val+=sum; if(!vis[x][y][next.val]){ vis[x][y][next.val]=true; q.push(next); } } } } } int main(){ int t,x,y,ca=1; int nx[10],ny[10]; while(scanf("%d%d%d",&n,&m,&l)!=EOF,(n+m+l)){ memset(s_pos.map,false,sizeof(s_pos.map)); memset(map,false,sizeof(map)); s_pos.val=0; move=((l<<1)-4); for(int i=0;i<l;i++) { scanf("%d%d",&x,&y); nx[i]=x;ny[i]=y; s_pos.map[x][y]=true; if(i>0){ for(int j=0;j<4;j++){ if(x+dx[j]==nx[i-1]&&y+dy[j]==ny[i-1]){ s_pos.val=(s_pos.val<<2)+j; break; } } } } s_pos.head[0]=nx[0], s_pos.head[1]=ny[0]; s_pos.tail[0]=nx[l-1];s_pos.tail[1]=ny[l-1]; scanf("%d",&t); s_pos.step=0; for(int i=0;i<t;i++){ scanf("%d%d",&x,&y); map[x][y]=true; s_pos.map[x][y]=true; } find=0; bfs(); printf("Case %d: ",ca++); if(find){ printf("%d\n",ans); } else printf("-1\n"); } return 0; }
下面是优化的代码:
#include<cstdio> #include<queue> #include<cstring> #include<cstdlib> using namespace std; const int maxn =21; int n,m,l,fond,ans,move,ca; bool map[maxn][maxn]; int cnt[maxn][maxn]; int dx[]={1,-1,0,0}; int dy[]={0,0,1,-1}; unsigned char vis[maxn][maxn][1<<14]; inline bool check(int x,int y){ return x>=1&&x<=n&&y>=1&&y<=m; } struct node{ int head[2],tail[2]; bool map[maxn][maxn]; int step,val; bool operator <(const node &a) const{ return cnt[a.head[0]][a.head[1]]+a.step<cnt[head[0]][head[1]]+step; } }s_pos; void get_min(){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cnt[i][j]=1000000; cnt[1][1]=0; queue<int > q;q.push(1); q.push(1); while(!q.empty()){ int x=q.front(); q.pop();int y=q.front();q.pop(); for(int i=0;i<n;i++){ int nx=x+dx[i]; int ny=y+dy[i]; if(check(nx,ny)){ if(map[nx][ny]) continue ; if(cnt[x][y]+1<cnt[nx][ny]){ cnt[nx][ny]=cnt[x][y]+1; q.push(nx); q.push(ny); } } } } } void bfs(){ priority_queue<node > q; q.push(s_pos); vis[s_pos.head[0]][s_pos.head[1]][ s_pos.val] =true; while(!q.empty()){ node now = q.top(); q.pop(); if(now.head[0]==1&&now.head[1]==1){ fond=1; ans=now.step; return ; } for(int i=0;i<4;i++){ node next = now; next.step+=1; int x=now.head[0]+dx[i]; int y=now.head[1]+dy[i]; if(check(x,y)){ if(next.map[x][y]) continue; next.head[0]=x; next.head[1]=y; next.map[x][y]=true; next.map[now.tail[0]][now.tail[1]]=false; int t= next.val&3; next.tail[0]=now.tail[0]+dx[t]; next.tail[1]=now.tail[1]+dy[t]; next.val=next.val>>2; int sum=i<<move; next.val+=sum; if(vis[x][y][next.val]!=ca){ vis[x][y][next.val]=ca; q.push(next); } } } } } int main(){ int t,x,y; int nx[10],ny[10]; ca=1; while(scanf("%d%d%d",&n,&m,&l)!=EOF,(n+m+l)){ memset(s_pos.map,false,sizeof(s_pos.map)); memset(map,false,sizeof(map)); s_pos.val=0; move=((l<<1)-4); for(int i=0;i<l;i++) { scanf("%d%d",&x,&y); nx[i]=x;ny[i]=y; s_pos.map[x][y]=true; if(i>0){ for(int j=0;j<4;j++){ if(x+dx[j]==nx[i-1]&&y+dy[j]==ny[i-1]){ s_pos.val=(s_pos.val<<2)+j; break; } } } } s_pos.head[0]=nx[0], s_pos.head[1]=ny[0]; s_pos.tail[0]=nx[l-1];s_pos.tail[1]=ny[l-1]; scanf("%d",&t); s_pos.step=0; for(int i=0;i<t;i++){ scanf("%d%d",&x,&y); map[x][y]=true; s_pos.map[x][y]=true; } fond=0; get_min(); bfs(); printf("Case %d: ",ca++); if(fond){ printf("%d\n",ans); } else printf("-1\n"); } return 0; }