拯救大兵瑞恩

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 264    Accepted Submission(s): 106

Problem Description
   1944年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但是幸好麦克得到了迷宫的地形图。
   迷宫的外形是一个长方形,其在南北方向被划分为N行,在东西方向被划分为M列,于是整个迷宫被划分为N*M个单元。我们用一个有序数对(单元的行号,单元的列号)来表示单元位置。南北或东西方向相邻的两个单元之间可以互通,或者存在一扇锁着的门,又或者存在一堵不可逾越的墙。迷宫中有一些单元存放着钥匙,并且所有的门被分为P类,打开同一类的门的钥匙相同,打开不同类的门的钥匙不同。
   大兵瑞恩被关押在迷宫的东南角,即(N,M)单元里,并已经昏迷。迷宫只有一个入口,在西北角,也就是说,麦克可以直接进入(1,1)单元。另外,麦克从一个单元移动到另一个相邻单元的时间为1,拿取所在单元的钥匙的时间以及用钥匙开门的时间忽略不计。
   你的任务是帮助麦克以最快的方式抵达瑞恩所在单元,营救大兵瑞恩。
 
Input
有多组数据对于每一组数据来说:
第一行是三个整数,依次表示N,M,P的值;
第二行是一个整数K,表示迷宫中门和墙的总个数;
第I+2行(1<=I<=K),有5个整数,依次为Xi1,Yi1,Xi2,Yi2,Gi:
当Gi>=1时,表示(Xi1,Yi1)单元与(Xi2,Yi2)单元之间有一扇第Gi类的门,当Gi=0时,表示(Xi1,Yi1)单元与(Xi2,Yi2)单元之间有一堵不可逾越的墙;
(其中,|Xi1-Xi2|+|Yi1-Yi2|=1,0<=Gi<=P)
第K+3行是一个整数S,表示迷宫中存放的钥匙总数;
第K+3+J行(1<=J<=S),有3个整数,依次为Xi1,Yi1,Qi:表示第J把钥匙存放在(Xi1,Yi1)单元里,并且第J把钥匙是用来开启第Qi类门的。(其中1<=Qi<=P)
注意:输入数据中同一行各相邻整数之间用一个空格分隔。

参数设定:
3<=N,M<=15;
1<=P<=10;

 
Output
对于每一组数据,输出一行,只包含一个整数T,表示麦克营救到大兵瑞恩的最短时间的值,若不存在可行的营救方案则输出-1。
 
Sample Input
4 4 9
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2
4 2 1
 
Sample Output
14
 

题目链接:HDU 4845

很显然用三元组$(x,y,state)$表示当前x、y坐标,获取的钥匙情况,而且这样是可以唯一确定状态的,然后钥匙获取情况用状态压缩表示即可

代码:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 16;
struct info
{
int x, y;
int keyst, step;
info() {}
info(int _x, int _y, int _keyst, int _step): x(_x), y(_y), keyst(_keyst), step(_step) {}
};
int dir[4][2] = {{1, 0}, {0, 1}, { -1, 0}, {0, -1}};
int door[N][N][N][N];
int key[N][N];
int d[N][N][1 << 11];
bool vis[N][N][1 << 11];
int n, m, p, k, s; void init()
{
CLR(door, 0);
CLR(key, 0);
CLR(d, INF);
CLR(vis, false);
}
inline bool check(const int &x, const int &y)
{
return x >= 1 && x <= n && y >= 1 && y <= m;
}
void bfs()
{
queue<info>Q;
info S(1, 1, 0 | key[1][1], 0);
Q.push(S);
vis[S.x][S.y][S.keyst] = true;
d[S.x][S.y][S.keyst] = 1;
while (!Q.empty())
{
info u = Q.front();
Q.pop();
for (int i = 0; i < 4; ++i)
{
int vx = u.x + dir[i][0];
int vy = u.y + dir[i][1];
if (!check(vx, vy))
continue;
int need = door[u.x][u.y][vx][vy];
if (need == -1)
continue;
if ((need == 0 || (u.keyst & (1 << need))))
{
int vkeyst = u.keyst | (key[vx][vy]);
if (!vis[vx][vy][vkeyst])
{
vis[vx][vy][vkeyst] = true;
d[vx][vy][vkeyst] = u.step + 1;
Q.push(info(vx, vy, vkeyst, d[vx][vy][vkeyst]));
}
}
}
}
}
int main(void)
{
int i;
while (~scanf("%d%d%d", &n, &m, &p))
{
init();
scanf("%d", &k);
for (i = 0; i < k; ++i)
{
int x1, x2, y1, y2, g;
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &g);
if (!g)
door[x1][y1][x2][y2] = door[x2][y2][x1][y1] = -1;
else
door[x1][y1][x2][y2] = door[x2][y2][x1][y1] = g;
}
scanf("%d", &s);
for (i = 0; i < s; ++i)
{
int x1, y1, qi;
scanf("%d%d%d", &x1, &y1, &qi);
key[x1][y1] |= (1 << qi);
}
bfs();
int ans = INF;
int Alst = (1 << (p + 1));
for (i = 0; i < Alst; ++i)
if (d[n][m][i] < ans)
ans = d[n][m][i];
printf("%d\n", ans == INF ? -1 : ans);
}
return 0;
}

最新文章

  1. Ural 1057 Amount of Degrees
  2. 复旦高等代数 II(15级)思考题
  3. hive 函数 Cube
  4. BZOJ2301 莫比乌斯反演
  5. 学习Linux第五天
  6. iOS在线音乐播放SZKAVPlayer(基于AVPlayer的封装)
  7. IE6 背景透明
  8. 需要插入子集的时候如何更新父级ID
  9. Django filter中用contains 在mysql中的问题
  10. Android OpenGL ES 应用(二) 纹理
  11. 201521123112《Java程序设计》第8周学习总结
  12. ZOJ 3557 &amp; BZOJ 2982 combination[Lucas定理]
  13. hdu4143 A Simple Problem
  14. 8、D8: Default interface methods are only supported starting with Android N (--min-api 24): void
  15. “学习CSS布局” 笔记
  16. C++的子类与父类强制转换产生的问题
  17. keepalived nginx 双机热备图文讲解
  18. Android 面试知识集1
  19. ITOO之底层关系
  20. tornado框架的get方法传递参数

热门文章

  1. 【51nod1299】监狱逃离(树形DP)
  2. 【转】Nginx搭建反向代理服务器过程详解
  3. Dtree 添加 checkbox 复选框 可以默认选中
  4. C/C++程序基础 (七)继承和多态
  5. nginx下根据指定路由重定向
  6. LNMP源码安装脚本
  7. ZendFramework-2.4 源代码 - ViewManager类图
  8. php中foreach循环遍历二维数组
  9. 17.VUE学习之- v-for指令的使用方法
  10. 第1-5章 慕课网微信小程序开发学习笔记