吴昊品游戏核心算法 Round 13(特别篇)—— 另一种迷宫游戏AI(queue容器+BFS)

 

 

  另外一种迷宫游戏来自(HDOJ的1072)。刚才那个应该还不能说是游戏吧!因为只是一些迷宫类游戏的关键技术,还不具备有游戏性(所谓游戏性,可以参 考任天堂公司给出的定义)。这里,Ignatius给出了游戏的规则——五个数字标注了五种不同的图标(这里考虑五种位图,数字0代表墙,数字1代表可以 通过的路线,数字2代表起始的地方,数字3代表Ignatius的目标位置,而数字4代表了一种很新颖的道具,这个道具我们接了之后,可以将时间重置为6 分钟)这里考虑一点,最开始的时间为6分钟,每走一步要减少一分钟,我们必须要在规定的时间之内走到终点(当然,这里有RESET的装备),不然的话,炸 弹就会爆炸,我们需要计算出到达目标的最优解(这里的最优参量定义为最小时间)

  和前面一款游戏比较类似,这里的游戏有一种“逃离迷宫”的感觉。同样地,我们定义一种二维数组mark[][]来定义每个格子所代表的最优状态,方向数组 当然是少不了的。不同的是,我们考虑将node结构体定义两个描述时间的变量,用time表示还剩下的时间,而用cnt表示需要花费的时间。也许,你觉得 这是不是具有重复定义的嫌疑?不是的,在代码中我阐述了为什么要定义两个表述时间的变量。而在这里,关于时间的最优解,确实不好界定,这里是否可以达到最 优呢?不知道能不能通过理论方法来证明出来(但是毕竟这里对于每一步都考虑优化了),但是由于对于给定的样例都AC了,可以说,如果样例不是太强的话,应 该是没有问题的。

  

  1 #include<iostream>
  2  //这里还是运用队列容器来实现 
  3  #include<queue>  
  4  using namespace std;  
  5  
  6  //首先是地图map[][],mark[][]保存到达该点时所剩的时间,n,m为地图的实际的长和宽,(si,sj)为开始的点,mins
  7  int map[9][9],mark[9][9],n,m,mins,si,sj;  
  8  
  9  //方向数组
 10  int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};  
 11  
 12  struct node  
 13  {  
 14    //time 剩余时间;cnt 已花时间
 15    int x,y,time,cnt;  
 16  };  
 17 
 18  node f;  
 19 
 20  void bfs()  
 21  {  
 22    f.x=si;
 23    f.y=sj;
 24    //已花的时间为0,而剩余的时间为6  
 25    f.cnt=0;
 26    f.time=6;  
 27    queue<node> q;  
 28    q.push(f);
 29    //这里标注第一个点的所剩的时间 
 30    mark[si][sj]=6;
 31    //如果队列整个空了,则退出 
 32    while(!q.empty())  
 33    {  
 34      node t=q.front();  
 35      q.pop();  
 36      if(map[t.x][t.y]==3)  
 37      {  
 38        //找到终点了,如果还剩余时间的话,将已经花费的时间输出
 39        if(t.time>0)  
 40        {  
 41          mins=t.cnt;  
 42          return;  
 43        }  
 44        else continue;  
 45      }  
 46      //如果踩到了重置时间的机关,则重置时间,并标记当前位置的时间
 47      if(map[t.x][t.y]==4)  
 48      {  
 49        t.time=6;  
 50        mark[t.x][t.y]=6;  
 51      }  
 52      for(int k=0;k<4;k++)  
 53      {  
 54        //定义一个NEXT结点,这个在前面的吴昊系列已经阐述过了
 55        node b;  
 56        b.x=t.x+dir[k][0];  
 57        b.y=t.y+dir[k][1];
 58        //将已经花费的时间++,而剩余的时间--  
 59        b.cnt=t.cnt+1;  
 60        b.time=t.time-1;  
 61        /*
 62          入队的条件,这里有如下一些条件:
 63          (1)首先,必须在迷宫的范围之内
 64          (2)这个位置不是一堵墙
 65          (3)目前还存在剩余时间
 66          (4)这个位置标识的最小需要时间必须小于实际的剩余时间(这样才能起到不断优化的作用),由此能不能就判断出是最小值呢?不一定,所以这里也置疑吧!
 67        */
 68        if(b.x<=n&&b.x>0&&b.y<=m&&b.y>0&&map[b.x][b.y]!=0&&t.time>0&&mark[b.x][b.y]<b.time)  
 69        {  
 70          mark[b.x][b.y]=b.time;  
 71          q.push(b);  
 72        }  
 73      }  
 74    }  
 75  }  
 76 
 77  int main()  
 78  {  
 79    int t;
 80    //样例的总数 
 81    cin>>t;  
 82    while(t--)  
 83    {
 84      //地图的长与宽
 85      cin>>n>>m;  
 86      for(int i=1;i<=n;i++)  
 87      {  
 88        for(int j=1;j<=m;j++)  
 89        {
 90          //将地图中的元素进行分类
 91          cin>>map[i][j];  
 92          if(map[i][j]==2)
 93          {  
 94            si=i;
 95            sj=j;  
 96            mark[i][j]=0;  
 97          }  
 98        }  
 99      }
100      //设置一个极大的时间,如果这个时间没有经过任何改动的话,判定出死亡了
101      mins=1000;  
102      bfs();  
103      if(mins!=1000)  
104        cout<<mins<<endl;  
105      else cout<<"-1"<<endl;  
106    }
107    return 0;  
108  }

 

posted on 2013-02-28 14:54  吴昊系列  阅读(199)  评论(0编辑  收藏  举报

导航