hdu 1254-推箱子

来源:互联网 发布:php基础知识测试题 编辑:程序博客网 时间:2024/05/29 04:06

一道wa到吐的题

链接:1254

解题原理很简单,单点到单点的最短路径问题可以bfs求,有个限制是不能拉箱子,造成推到墙角墙边就不能退回原位了,换种思路其实就是人能不能走到箱子前进方向的背面也就是游戏上推箱子时人站的位置,这是一个简单的连通问题,dfs或者dfs都能求解。

需要注意的一点是箱子的当前位置也看作是墙。

wa到吐的原因是我忽略了每次推动箱子的状态不只是单纯的有箱子的位置(看来还是小时候游戏打少了( ̄▽ ̄)"),还有人和箱子的相对位置,也就是只要箱子是从不同方向进入同一个点都具有实际意义。

解决方法可以一是开大四倍标记访问情况的数组分别对应四种方向,但这题状态数量最多才为7*7*4种,可以直接对状态编码然后通过set来判重,这里编码是根据人的位置和箱子位置的坐标来编码,比如箱子在1,1,人的位置在2,1,则可以编码为1121。

代码:

//问题的关键在于箱子位置可以重复多次进入但状态不能重复#include<iostream>#include<cstring>#include<set>#include<queue>using namespace std;const int MaxN=10;int p[MaxN][MaxN];int MaxI,MaxJ;bool walk(int bi,int bj,int ei,int ej){   if(ei<0||ej<0||ei>MaxI-1||ej>MaxJ-1)return 0;   struct node{      int i,j;      node(int a=0,int b=0):i(a),j(b){}   };   queue<node> q;   bool vis[MaxN][MaxN];   memset(vis,0,sizeof(vis));   q.push(node(bi,bj));   node at;   while(!q.empty()){      at=q.front();      q.pop();      vis[at.i][at.j]=1;      if(at.i==ei&&at.j==ej)return 1;      if(at.i>0&&vis[at.i-1][at.j]==0&&p[at.i-1][at.j]!=1)q.push(node(at.i-1,at.j));      if(at.i<MaxI-1&&vis[at.i+1][at.j]==0&&p[at.i+1][at.j]!=1)q.push(node(at.i+1,at.j));      if(at.j>0&&vis[at.i][at.j-1]==0&&p[at.i][at.j-1]!=1)q.push(node(at.i,at.j-1));      if(at.j<MaxJ-1&&vis[at.i][at.j+1]==0&&p[at.i][at.j+1]!=1)q.push(node(at.i,at.j+1));   }   return 0;}int coding(int a,int b,int c,int d){   return a+b*10+c*100+d*1000;}int promote(int bi,int bj,int ei,int ej,int pi,int pj){   struct node{      int i,j,li,lj;      node(int a=0,int b=0,int c=0,int d=0):i(a),j(b),li(c),lj(d){}   };   int dis[MaxN][MaxN];   memset(dis,0,sizeof(dis));   set<int> code;   queue<node> q;   q.push(node(bi,bj,pi,pj));   node at;   while(!q.empty()){      at=q.front();      q.pop();      code.insert(coding(at.i,at.j,at.li,at.lj));      p[at.i][at.j]=1;      dis[at.i][at.j]=dis[at.li][at.lj]+1;      if(at.i==ei&&at.j==ej)return dis[at.i][at.j]-1;      if(at.i>0&&p[at.i-1][at.j]!=1&&code.count(coding(at.i-1,at.j,at.i,at.j))==0&&walk(at.li,at.lj,at.i+1,at.j))q.push(node(at.i-1,at.j,at.i,at.j));      if(at.i<MaxI-1&&p[at.i+1][at.j]!=1&&code.count(coding(at.i+1,at.j,at.i,at.j))==0&&walk(at.li,at.lj,at.i-1,at.j))q.push(node(at.i+1,at.j,at.i,at.j));      if(at.j>0&&p[at.i][at.j-1]!=1&&code.count(coding(at.i,at.j-1,at.i,at.j))==0&&walk(at.li,at.lj,at.i,at.j+1))q.push(node(at.i,at.j-1,at.i,at.j));      if(at.j<MaxJ-1&&p[at.i][at.j+1]!=1&&code.count(coding(at.i,at.j+1,at.i,at.j))==0&&walk(at.li,at.lj,at.i,at.j-1))q.push(node(at.i,at.j+1,at.i,at.j));      p[at.i][at.j]=0;   }   return -1;}int main(){   int n;   int a,b,c,d,e,f;   cin>>n;   while(n--){      cin>>MaxI>>MaxJ;      for(int i=0;i<MaxI;i++){         for(int j=0;j<MaxJ;j++){            cin>>p[i][j];            if(p[i][j]==2){               a=i;b=j;            }            else if(p[i][j]==3){               c=i;d=j;            }            else if(p[i][j]==4){               e=i;f=j;            }         }      }      cout<<promote(a,b,c,d,e,f)<<endl;   }}


原创粉丝点击