HDU 5025Saving Tang Monk BFS + 二进制枚举状态
3A的题目,第一次TLE,是因为一次BFS起点到终点状态太多爆掉了时间。
第二次WA,是因为没有枚举蛇的状态。
解体思路:
因为蛇的数目是小于5只的,那就首先枚举是否杀死每只蛇即可。
然后多次BFS,先从起点到第一把钥匙,不能往回走,要用VIS数组标记。
第二次从第一把钥匙走到第二把钥匙。
最后一次从最后一把钥匙走到终点即可。
Tips 1: 在每次BFS过程中使用优先队列保证每次是最小步长的状态。
Tips2 :使用二进制枚举蛇的状态
Tips3:首先使用DFS判断是否绝对有解,如果无解输出"impossible",如果有解则继续。
Tips4:多次 BFS,而不是一次BFS,否则会导致状态太多TLE
代码如下:
//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define ll long long
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#define Min(a,b) (((a) < (b)) ? (a) : (b))
#define Abs(x) (((x) > 0) ? (x) : (-(x)))
using namespace std; const int INF = 0x3f3f3f3f;
const int MAXN = ;
const double eps = 1e-; struct node{
int x,y,step;
}; char map[][];
int vis[][];
int to[][]= {,,-,,,,,-};
int n,m,sx,sy,ex,ey,ans; bool operator < (node a, node b){
return a.step > b.step;
} int check(int x,int y){
if(x< || x>=n || y< || y>=n)
return ;
if(map[x][y]=='#' || vis[x][y])
return ;
return ;
} void bfs(int sx, int sy, int k){
int i;
priority_queue <node> Q;
node a,next;
a.x = sx;
a.y = sy;
a.step = ;
vis[a.x][a.y]=;
Q.push(a);
while(!Q.empty()){
a = Q.top();
//printf("x = %d y = %d step = %d\n",a.x,a.y,a.step);
Q.pop();
if(k <= m){
if(map[a.x][a.y] == k + ''){
ans += a.step;
ex = a.x;
ey = a.y;
//printf("%d %d cur _ ans = %d\n",ex, ey,ans);
return;
}
} else{
if(map[a.x][a.y] == 'T'){
ans += a.step;
ex = a.x;
ey = a.y;
//printf("%d %d cur _ ans = %d\n",ex, ey,ans);
return;
}
}
for(i = ; i<; i++){
next = a;
next.x+=to[i][];
next.y+=to[i][];
if(check(next.x,next.y)) continue;
next.step=a.step+;
if(map[a.x][a.y] == 'S'){
++next.step;
}
vis[next.x][next.y] = ;
Q.push(next);
}
if(map[a.x][a.y] == 'S'){
map[a.x][a.y] = '.';
}
}
ans =INF;
return ;
} void dfs(int x, int y){
for(int i = ; i<; i++){
int _x = x + to[i][];
int _y = y + to[i][];
if(check(_x,_y)) continue;
if(map[_x][_y] != '#'){
vis[_x][_y] = ;
dfs(_x,_y);
}
}
}
int main(){
int i,j,cc,s_flag;
while(EOF != scanf("%d%d",&n,&m)){
if(n == && m == ) break;
s_flag = ;
node S[];
for(i = ; i<n; i++)
scanf("%s",map[i]);
for(i = ; i<n; i++){
for(j = ; j<n; j++){
if(map[i][j]=='K'){
sx = i;
sy = j;
}else if(map[i][j] == 'T'){
ex = i,ey = j;
}else if(map[i][j] == 'S'){
S[s_flag].x = i, S[s_flag++].y = j;
}
}
}
memset(vis,,sizeof(vis));
vis[sx][sy] = ;
dfs(sx,sy);
int kkk[];
bool flag = false;
memset(kkk, , sizeof(kkk));
for(i = ; i < n; ++i){
for(j = ; j < n; ++j){
if(map[i][j] >= '' && map[i][j] <= '' && vis[i][j]){
kkk[map[i][j] - ''] = ;
}
}
}
for(i = ; i <= m; ++i){
if(!kkk[i]) break;
}
if(i == m + ) flag = true; if(vis[ex][ey] == || !flag){
printf("impossible\n");
continue;
}
s_flag = ;
for(i = ; i<n; i++){
for(j = ; j<n; j++){
if(map[i][j] == 'S'){
S[s_flag].x = i, S[s_flag++].y = j;
}
}
}
int minans=INF;
for(cc = ; cc < ( << s_flag); ++cc){
ans = ;
for(i = ; i <s_flag; ++i){
if(( << i) & cc){
map[S[i].x][S[i].y] = '.';
ans++;
}
else {
map[S[i].x][S[i].y] = '#';
}
}
for(i = ; i < n; ++i){
for(j = ; j < n; ++j){
if(map[i][j] == 'K'){
ex = i;
ey = j;
}
}
}
for(int k = ; k <= m + ; ++k){
memset(vis, , sizeof(vis));
sx = ex;
sy = ey;
bfs(sx, sy, k);
}
minans=min(minans,ans);
}
printf("%d\n",minans);
}
return ;
}
HDU 5025Saving Tang Monk BFS + 二进制枚举状态的更多相关文章
- 【uva 1151】Buy or Build(图论--最小生成树+二进制枚举状态)
题意:平面上有N个点(1≤N≤1000),若要新建边,费用是2点的欧几里德距离的平方.另外还有Q个套餐,每个套餐里的点互相联通,总费用为Ci.问让所有N个点连通的最小费用.(2组数据的输出之间要求有换 ...
- HDU 5025 Saving Tang Monk --BFS
题意:给一个地图,孙悟空(K)救唐僧(T),地图中'S'表示蛇,第一次到这要杀死蛇(蛇最多5条),多花费一分钟,'1'~'m'表示m个钥匙(m<=9),孙悟空要依次拿到这m个钥匙,然后才能去救唐 ...
- HDU 5094 --Maze【BFS && 状态压缩】
Maze Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 100000/100000 K (Java/Others) Total Sub ...
- HDU 5025 Saving Tang Monk 【状态压缩BFS】
任意门:http://acm.hdu.edu.cn/showproblem.php?pid=5025 Saving Tang Monk Time Limit: 2000/1000 MS (Java/O ...
- [ACM] HDU 5025 Saving Tang Monk (状态压缩,BFS)
Saving Tang Monk Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- hdu 5025 Saving Tang Monk(bfs+状态压缩)
Description <Journey to the West>(also <Monkey>) is one of the Four Great Classical Nove ...
- HDU 5025:Saving Tang Monk(BFS + 状压)
http://acm.hdu.edu.cn/showproblem.php?pid=5025 Saving Tang Monk Problem Description <Journey to ...
- hdu 5025 Saving Tang Monk 状态压缩dp+广搜
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4092939.html 题目链接:hdu 5025 Saving Tang Monk 状态压缩 ...
- ACM学习历程—HDU 5025 Saving Tang Monk(广州赛区网赛)(bfs)
Problem Description <Journey to the West>(also <Monkey>) is one of the Four Great Classi ...
随机推荐
- IOS 使用IOS6苹果地图
IOS应用程序中使用Map Kit API开发地图应用程序.其核心是MKMapView类的使用.我们可以设置地图显示方式,控制地图,可以在地图上添加标注. 1.显示地图 在Map Kit API中显示 ...
- char[]转换成wchar_t的转换方法(GNU Libc规定wchar_t为32位)
wchar_t是C/C++的字符数据类型,是一种扩展的字符存储方式,wchar_t类型主要用在国际化程序的实现中,但它不等同于unicode编码.unicode编码的字符一般以wchar_t类型存储. ...
- STL deque详解
英文原文:http://www.codeproject.com/Articles/5425/An-In-Depth-Study-of-the-STL-Deque-Container 绪言 这篇文章深入 ...
- perl5 第一章 概述
第一章 概述 by flamephoenix 一.Perl是什么?二.Perl在哪里?三.运行四.注释 一.Perl是什么? Perl是Practical Extraction and Re ...
- The Longest Straight(二分,离散化)
Problem 2216 The Longest Straight Accept: 7 Submit: 14 Time Limit: 1000 mSec Memory Limit : 3 ...
- I can do it!(贪心)
I can do it! Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- 利用copy函数简单快速输出/保存vector向量容器中的数据
如果要输出vector中的数据我们可以通过循环语句输出,更加简便的方法是利用copy函数直接输出,例子: #include "stdafx.h" #include <iost ...
- C++设计模式实现--组合(Composite)模式
一. 举例 这个样例是书上的,如果有一个公司的组结结构例如以下: 它的结构非常像一棵树,当中人力资源部和財务部是没有子结点的,详细公司才有子结点. 并且最关健的是,它的每一层结构非常相似. 代码实现例 ...
- ADO.NET基础笔记
ADO.NET 程序要和数据库交互要通过ADO.NET进行,通过ADO.Net就能在程序中执行SQL了. ADO.Net中提供了对各种不同的数据库的统一操作接口. 连接字符串: 程序通过连接字符串指定 ...
- java源代码如何打成jar包
链接地址:http://jingyan.baidu.com/article/046a7b3ed8b23ef9c27fa9b9.html 有时自已写了一个很巧妙的方法,想分享给别人用,这时我们就可以将其 ...