最后两题算是这个专题最难的两题了

这题关键是标记数组

我一开始设置的是 四维的  第三维是朝向  第四维是钥匙个数

但是 不同的取法钥匙个数可能会重复   如:取ab钥匙和取ac钥匙都是两枚  导致wa

然后学了状态压缩   用位运算来表示

因为一共十把钥匙  2的十次方才1024   所以开一个1024的数组就行了

int vis[25][25][1025];

当遇到门时   &运算:

if(v.n&(1<<(m1[v.x][v.y]-'A')))
{
vis[u.x][u.y][u.n]=1;
q.push(v);
}

  

遇到钥匙的时候:|运算

v.n=v.n|(1<<(m1[v.x][v.y]-'a'));

太巧妙了

#include<bits/stdc++.h>
using namespace std; char m1[][];
int n,m,sx,sy,ex,ey,t;
int vis[][][]; struct node
{
int x,y,d,n; }; bool inmap(int x,int y)
{
if(x>=&&x<=n&&y>=&&y<=m)return true;
return false; } void bfs()
{
memset(vis,,sizeof(vis));
int dx[]={,,,-};
int dy[]={,,-,};
node u;
u.x=sx;u.y=sy;u.d=;u.n=; queue<node>q;
q.push(u); m1[sx][sy]='.';
while(!q.empty())
{
u=q.front();q.pop();
// printf("%d %d %d %d\n",u.x,u.y,u.d,u.n);
if(u.d<=t-&&m1[u.x][u.y]=='^'){printf("%d\n",u.d);return;} for(int i=;i<;i++)
{
node v=u;
v.x+=dx[i];
v.y+=dy[i];
v.d=v.d+;
if(inmap(v.x,v.y)&&m1[v.x][v.y]!='*'&&vis[v.x][v.y][v.n]==&&v.d<t)
{
if(m1[v.x][v.y]>='a'&&m1[v.x][v.y]<='j')
{
v.n=v.n|(<<(m1[v.x][v.y]-'a'));
vis[u.x][u.y][u.n]=;
q.push(v); } if(m1[v.x][v.y]>='A'&&m1[v.x][v.y]<='J')
{
if(v.n&(<<(m1[v.x][v.y]-'A')))
{
vis[u.x][u.y][u.n]=;
q.push(v);
}
}
if((m1[v.x][v.y]=='^'||m1[v.x][v.y]=='.'))
{q.push(v);vis[v.x][v.y][v.n]=;}
}
}
}
printf("-1\n"); }
int main()
{ while(scanf("%d%d%d",&n,&m,&t)==)
{
getchar();
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{scanf("%c",&m1[i][j]);
if(m1[i][j]=='@'){sx=i;sy=j;}
if(m1[i][j]=='^'){ex=i;ey=j;}
}
getchar();
} bfs(); getchar(); }
return ;
}

回顾:

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 20+5
#define inf 0x3f3f3f3f
int dx[]={,,,-};
int dy[]={,-,,};
int sx,sy,ex,ey,k;
int n,m;
char mp[N][N]; bool inmap(int x,int y)
{
return x>=&&x<=n&&y>=&&y<=m;
} struct node
{
int x,y,d,key;
}; int vis[N][N][<<]; void bfs()
{
memset(vis,,sizeof vis);
node u,v;
u.x=sx;
u.y=sy;
u.d=;
u.key=;
vis[sx][sy][]=;
queue<node>q;
q.push(u);
while(!q.empty())
{
u=q.front();q.pop();
// printf("%d %d %d\n",u.x,u.y,u.d); if(mp[u.x][u.y]=='^'&&u.d<k){printf("%d\n",u.d);return;} for(int i=;i<;i++)
{
node v=u;
v.x+=dx[i];
v.y+=dy[i];
v.d+=;
if(v.d>=k)continue; if(islower(mp[v.x][v.y]))
v.key=v.key|( <<(mp[v.x][v.y]-'a') );
if(isupper(mp[v.x][v.y]))
if(( v.key&(<<(mp[v.x][v.y]-'A')) )== )continue; if(inmap(v.x,v.y)&&mp[v.x][v.y]!='*'&&!vis[v.x][v.y][v.key])
{
q.push(v);
vis[v.x][v.y][v.key]=; } } }
printf("-1\n");
} int main()
{
while(scanf("%d%d%d",&n,&m,&k)==)
{
for(int i=;i<=n;i++)
scanf("%s",mp[i]+); for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j]=='@'){sx=i;sy=j;}
bfs();
}
return ;
}

胜利大逃亡 HDU1429 (bfs)的更多相关文章

  1. hdu.1429.胜利大逃亡(续)(bfs + 0101011110)

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  2. hdu 1429 胜利大逃亡(续)(bfs+位压缩)

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  3. HDU-1253 胜利大逃亡 (BFS)

    此题可以做为三维深搜模板题.. 胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Ot ...

  4. HDU1253 胜利大逃亡 (BFS)

      胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  5. hdu 1429 胜利大逃亡(续) (bfs+状态压缩)

    又开始刷题了 题意:略过. 分析:主要是确定状态量,除了坐标(x,y)之外,还有一个key状态,就好比手上拿着一串钥匙.状态可以用位运算来表示:key&(x,y)表示判断有没有这扇门的钥匙,k ...

  6. HDOJ 1429 胜利大逃亡(续) (bfs+状态压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 思路分析:题目要求找出最短的逃亡路径,但是与一般的问题不同,该问题增加了门与钥匙约束条件: 考虑 ...

  7. 九度1456胜利大逃亡【BFS】

    时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:4432 解决:1616 题目描述: Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡 ...

  8. 胜利大逃亡,bfs,广度优先搜索

    题目描述: Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius ...

  9. HDOJ 1253 胜利大逃亡(bfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1253 思路分析:因为问题需要寻找到达终点的最短的距离(最短的步数),即在状态转换图上需要找出层次最浅的 ...

随机推荐

  1. C++中模板的使用

    为什么使用模板: C++重载(overloading),重载函数一般含有不同的参数个数或不同的参数类型.如果使用MAX函数对不同类型的求最大值,就要定义不同的重载函数: int max(int x,i ...

  2. D - Laying Cables Gym - 100971D (单调栈)

    题目链接:https://cn.vjudge.net/problem/Gym-100971D 题目大意:给你n个城市的信息,每一个城市的信息包括坐标和人数,然后让你找每一个城市的父亲,作为一个城市的父 ...

  3. linux笔记_day06

    1.用户:表示符,凭证 2.用户组:表示符 进程也是有属主和属组的 安全上下文(secure context): 用户:UID,/etc/pawwd 组:GID ,/etc/group 影子口令: 用 ...

  4. OGG实现两台Oracle数据库的同步

    今天通过最简单的一个例子,给大家讲解下 goldengate 实现两台Oracle数据库的同步.内容如下:1.配置数据库信息.2.安装golden gate.3.配置golden gate.4.测试同 ...

  5. python中argparse模块用法实例详解

    python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...

  6. diff 命令用法--如何打补丁【原创--学习笔记】

    diff 命令用法 1.”-u”:表示在比较结果中输出上下文中一些相同的行,这有利于人工定位 2.“-r“:表示递归比较各个子目录下的文件 3.“-N“:将不存在的文件当作空文件 4.“-w“:忽略对 ...

  7. NTFS文件系统简介

    原文地址:http://www.cnblogs.com/watertao/archive/2011/11/28/2266595.html 1.简介 NTFS(New Technology File S ...

  8. android margin--负的margin的使用

    通常情况下,如果我们想要两个控件实现重叠的效果,一般都是使用FrameLayout 或者RelativeLayout布局.其实,如果设置两个控件的margin值为负数,也能实显控件重叠的效果. 先展示 ...

  9. ios 获取视频截图

    #pragma mark -- 获取视频截图- (UIImage *)getThumbnailImage:(NSString *)videoURL{     AVURLAsset *asset = [ ...

  10. 调试Windows Service

    调试Windows Service 使用一般的调试方法调试不了Windows Servers,所以参考了一些调试方法 我服务源码中使用了Timer,注意不能使用工具箱内的Timer,用System.T ...