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 ...
随机推荐
- Tomcat+redis+nginx配置
为客户开发的一个绩效系统,采用了java web的开发方式,使用了一些spring mvc, mybatis之类的框架.相比于oracle ebs的二次开发,这种开发更加灵活,虽然和ebs集成的时候遇 ...
- HDU 1398 Square Coins
题目大意:有面值分别为.1,4,9,.......17^2的硬币无数多个.问你组成面值为n的钱的方法数. 最简单的母函数模板题: #include <cstdio> #include &l ...
- 自定义cell相关注意事项
1.拖线成功后,如果又在.h文件或者.m文件里面删除了对应的属性或者方法.一定要在xib文件中,删除关联.方法是:右键点击一下对应的UI控件,把多余的关联叉掉就行了. 不然容易崩溃.
- KMP算法的一个C++实现
本文参考阮一峰老师的KMP算法,重点是“部分匹配表”的建立.算法可参考 http://kb.cnblogs.com/page/176818/ . /* * kmp.cpp * Author: Qian ...
- linux driver: input子系统
<韦东山Linux视频第2期_从零写驱动\第13课第1节 输入子系统概念介绍_P.wmv> 本视频对输入子系统的结构进行了详细的剖析,通过本视频,可以了解到input核心包括了设备和han ...
- Xcode 新版本如何设置ARC
在刚刚开始学习IOS开发时,最好不要开启ARC,这样有助于学习内存管理,但不少刚刚接触Xcode的朋友可能会发现,当你使用最新版本的Xcode时,敲入release等代码时会提示报错.这是因为系统默认 ...
- (Problem 29)Distinct powers
Consider all integer combinations ofabfor 2a5 and 2b5: 22=4, 23=8, 24=16, 25=32 32=9, 33=27, 34=81, ...
- javascript 检测密码强度
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Spring Boot特性(转)
摘要: 1. SpringApplication SpringApplication 类是启动 Spring Boot 应用的入口类,你可以创建一个包含 main() 方法的类,来运行 SpringA ...
- 轻松搞定Linux端口转发
一 从一台机到另一台机端口转发 启用网卡转发功能 #echo 1 > /proc/sys/net/ipv4/ip_forward 举例:从192.168.0.132:21521(新端口)访问19 ...