[uva P1601] The Morning after Halloween

题目链接

非常经典的一道题目,lrj的书上也有(貌似是紫书?)。

其实这题看起来就比较麻烦。。

首先要保证小鬼不能相遇,也不能互相穿过。

可以用一个vis[][][]数组来表示三个小鬼的当前处于位置是否已经访问,

dis[][][]表示到某个状态是最小步数,用short存,可以卡住空间。

但是这样效率不高。注意到每四个格子里面至少有一个‘#’,所以我们可以把原来的网格图建一个隐式图,就可以避开很多冗余判断。

为了提高效率,我用了双向bfs。

其实就是在原来bfs基础上加点东西,代码量还是有点长的。

据说我的空间还是很大,在某些oj上会被卡。。所以还需要更优秀的标记。

code:

 %:pragma GCC optimize()
 #include<bits/stdc++.h>
 #define idx(i,j) ((i)*m+(j))
 #define Ms(a,x) memset(a,x,sizeof a)
 using namespace std;
 ,P=,fl[][]={{,},{-,},{,},{,-},{,}};
 ],lays;}cur,nxt;
 ],C[P]; char ch,a[N][N];
 short vis[P][P][P],dis[P][P][P];
 queue <sta> Q[];
 inline char read() {
     ch=getchar();
     while (ch!=' '&&ch!='#'&&!isalpha(ch)) ch=getchar();
     return ch;
 }
 void add(int u,int v) {G[u][C[u]++]=v;}
 bool jug(int x,int y) {
     ||x>n-||y<||y>m-) ;
     return a[x][y]!='#';
 }
 int update(int id) {
     ]][nxt.p[]][nxt.p[]]==-) {
         vis[nxt.p[]][nxt.p[]][nxt.p[]]=id;
         dis[nxt.p[]][nxt.p[]][nxt.p[]]=nxt.lays;
         Q[id].push(nxt);
         ;
     }]][nxt.p[]][nxt.p[]]==-id)
         ]][nxt.p[]][nxt.p[]];
     ;
 }
 int bfs(int id,int s) {
     while (!Q[id].empty()) {
         cur=Q[id].front();
         ;
         Q[id].pop();
         ) {
             nxt=cur,nxt.lays=s+;
             ,s1=C[cur.p[]]; i<s1; i++) {
                 nxt.p[]=G[cur.p[]][i];
                 int re=update(id);
                 if (~re) return re;
             }
         }else
         ) {
             nxt=cur,nxt.lays=s+;
             ,s1=C[cur.p[]]; i<s1; i++) {
                 nxt.p[]=G[cur.p[]][i];
                 ,s2=C[cur.p[]]; j<s2; j++) {
                     nxt.p[]=G[cur.p[]][j];
                     ]==nxt.p[]) continue;
                     ]==cur.p[]&&nxt.p[]==cur.p[]) continue;
                     int re=update(id);
                     if (~re) return re;
                 }
             }
         }else
         ) {
             nxt=cur,nxt.lays=s+;
             ,s1=C[cur.p[]]; i<s1; i++) {
                 nxt.p[]=G[cur.p[]][i];
                 ,s2=C[cur.p[]]; j<s2; j++) {
                     nxt.p[]=G[cur.p[]][j];
                     ]==nxt.p[]) continue;
                     ]==cur.p[]&&nxt.p[]==cur.p[]) continue;
                     ,s3=C[cur.p[]]; k<s3; k++) {
                         nxt.p[]=G[cur.p[]][k];
                         ]==nxt.p[]||nxt.p[]==nxt.p[]) continue;
                         ]==cur.p[]&&nxt.p[]==cur.p[]) continue;
                         ]==cur.p[]&&nxt.p[]==cur.p[]) continue;
                         int re=update(id);
                         if (~re) return re;
                     }
                 }
             }
         }
     }
     ;
 }
 int double_bfs() {
     ].empty()) Q[].pop();
     ].empty()) Q[].pop();
     Ms(vis,-),Ms(dis,);
     ; i<; i++) cur.p[i]=; cur.lays=;
     ; i<n; i++)
         ; j<m; j++)
             if (isupper(a[i][j])) cur.p[a[i][j]-'A']=idx(i,j);
     Q[].push(cur),vis[cur.p[]][cur.p[]][cur.p[]]=;
     ; i<; i++) cur.p[i]=; cur.lays=;
     ; i<n; i++)
         ; j<m; j++)
             if (islower(a[i][j])) cur.p[a[i][j]-'a']=idx(i,j);
     Q[].push(cur),vis[cur.p[]][cur.p[]][cur.p[]]=;
     ; !Q[].empty()&&!Q[].empty(); st++) {
         ,st),tag1=bfs(,st);
         if (~tag0) return tag0;
         if (~tag1) return tag1;
     }
     ;
 }
 int main() {
     while (scanf("%d%d%d",&m,&n,&t)!=EOF,n|m|t) {
         ; i<n; i++)
             ; j<m; j++)
                 a[i][j]=read(),C[idx(i,j)]=;
         ; i<n; i++)
             ; j<m; j++)
                 ; k<; k++) {
                     ],j+fl[k][])) continue;
                     add(idx(i,j),idx(i+fl[k][],j+fl[k][]));
                 }
         printf("%d\n",double_bfs());
     }
     ;
 }

[uva P1601] The Morning after Halloween的更多相关文章

  1. UVA 1601 The Morning after Halloween

    题意: 给出一个最大为16×16的迷宫图和至多3个ghost的起始位置和目标位置,求最少经过几轮移动可以使三个ghost都到达目标位置.每轮移动中,每个ghost可以走一步,也可以原地不动,需要注意的 ...

  2. Uva 1061 The Morning after Halloween

    基本思路是BFS: 1. 题目中已经说了,每相连的2X2格子中必有一个‘#’,也就是,每个点周围最多也就三个方向可以走.因此,可以把所有空格都提出来,形成一个图,直接遍历每条边,而不是每次判断4个方向 ...

  3. UVA - 1601 The Morning after Halloween (BFS/双向BFS/A*)

    题目链接 挺有意思但是代码巨恶心的一道最短路搜索题. 因为图中的结点太多,应当首先考虑把隐式图转化成显式图,即对地图中可以相互连通的点之间连边,建立一个新图(由于每步不需要每个鬼都移动,所以每个点需要 ...

  4. UVA - 1601 The Morning after Halloween (双向BFS&单向BFS)

    题目: w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...

  5. <<操作,&0xff以及|的巧妙运用(以POJ3523---The Morning after Halloween(UVa 1601)为例)

    <<表示左移,如a<<1表示将a的二进制左移一位,加一个0,&0xff表示取最后8个字节,如a&0xff表示取a表示的二进制中最后8个数字组成一个新的二进制数, ...

  6. uva 11237 - Halloween treats(抽屉原理)

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u011328934/article/details/37612503 题目链接:uva 11237 ...

  7. UVA 11237 - Halloween treats(鸽笼原理)

    11237 - Halloween treats option=com_onlinejudge&Itemid=8&page=show_problem&category=516& ...

  8. UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)

    题意 :w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...

  9. 【UVa】1601 The Morning after Halloween(双向bfs)

    题目 题目     分析 双向bfs,对着书打的,我还调了好久.     代码 #include<cstdio> #include<cstring> #include<c ...

随机推荐

  1. jsr-303 参数校验—自定义校验注解

    1.为什么要自定义? 通过上篇学习,了解到很多常用注解了,但是呢,总是有那么些需求....   2.案例分析(手机号格式) 2.1.需要验证的实体 Bean public class LoginVo ...

  2. 访问GitLab的PostgreSQL数据库,查询、修改、替换等操作

    1.登陆gitlab的安装服务查看配置文件 cat /var/opt/gitlab/gitlab-rails/etc/database.yml production: adapter: postgre ...

  3. (转)git 忽略规则

    对于经常使用Git的朋友来说,.gitignore配置一定不会陌生.废话不说多了,接下来就来说说这个.gitignore的使用. 首先要强调一点,这个文件的完整文件名就是".gitignor ...

  4. js 获取时区

    js的时区函数: 设datename为创建的一个Date对象 ====================datename.getTimezoneOffset()--取得当地时间和GMT时间(格林威治时间 ...

  5. Six advantages of Nissan consult 3 diagnostic tool

    Today autonumen.com introduces Nissan consult 3. Nissan Consult 3 is a professional diagnostic tool ...

  6. 基于ABP模块组件与依赖注入组件的项目插件开发

    注意,阅读本文,需要先阅读以下两篇文章,并且对依赖注入有一定的基础. 模块系统:http://www.cnblogs.com/mienreal/p/4537522.html 依赖注入:http://w ...

  7. 20190404用户及用户组管理(week1_day4)

    useradd userdel usermod groupadd groupdel 用户管理 为什么需要有用户? 1. linux是一个多用户系统 2. 权限管理(权限最小化) 用户:存在的目录是为了 ...

  8. codeforces #305 C Mike and Foam

    首先我们注意到ai<=50w 因为2*3*5*7*11*13*17=510510 所以其最多含有6个质因子 我们将每个数的贡献分离, 添加就等于加上了跟这个数相关的互素对 删除就等于减去了跟这个 ...

  9. laravel 分页使用

    分页 //对数据库结果分页 $users = DB::table('users')->paginate(15); //可以对 Eloquent 模型分页: $allUsers = User::p ...

  10. Docker Swarm 高可用详解

    Docker Swarm 高可用详解 Manager管理节点宕机后其他管理节点仍然可以使用管理 intermal distributed state store:内部分布式状态存储同步共享到每个节点. ...