hdu 1026:Ignatius and the Princess I(优先队列 + bfs广搜。ps:广搜AC,深搜超时,求助攻!)
Ignatius and the Princess I
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10541 Accepted Submission(s): 3205
Special Judge
1.Ignatius can only move in four directions(up, down, left, right), one step per second. A step is defined as follow: if current position is (x,y), after a step, Ignatius can only stand on (x-1,y), (x+1,y), (x,y-1) or (x,y+1).
2.The array is marked with some characters and numbers. We define them like this:
. : The place where Ignatius can walk on.
X : The place is a trap, Ignatius should not walk on it.
n : Here is a monster with n HP(1<=n<=9), if Ignatius walk on it, it takes him n seconds to kill the monster.
Your task is to give out the path which costs minimum seconds for Ignatius to reach target position. You may assume that the start position and the target position will never be a trap, and there will never be a monster at the start position.
.XX..
..X..
...X.
...XX.
XXXXX. .XX..
..X..
...X.
...XX.
XXXXX1 .XX...
..XX1.
...X.
...XX.
XXXXX.
It takes seconds to reach the target position, let me show you the way.
1s:(,)->(,)
2s:(,)->(,)
3s:(,)->(,)
4s:(,)->(,)
5s:(,)->(,)
6s:(,)->(,)
7s:(,)->(,)
8s:FIGHT AT (,)
9s:FIGHT AT (,)
10s:(,)->(,)
11s:(,)->(,)
12s:(,)->(,)
13s:(,)->(,)
FINISH
It takes seconds to reach the target position, let me show you the way.
1s:(,)->(,)
2s:(,)->(,)
3s:(,)->(,)
4s:(,)->(,)
5s:(,)->(,)
6s:(,)->(,)
7s:(,)->(,)
8s:FIGHT AT (,)
9s:FIGHT AT (,)
10s:(,)->(,)
11s:(,)->(,)
12s:(,)->(,)
13s:(,)->(,)
14s:FIGHT AT (,)
FINISH
God please help our poor hero.
FINISH
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
struct Way{
int x;
int y;
bool ism;
}way[]; //存储每一秒走到的位置,及有没有怪物
char maze[][];
bool isv[][];
int dx[]={,,,-};
int dy[]={,,-,};
int curx,cury;
int endx,endy;
int N,M;
int _min;
int dfs(int curx,int cury,int s) //当前的位置以及走到这个位置用的时间(秒)和方向
{
int n=;
if(curx==N- && cury==M-){
//到达终点
_min=s;
if(''<=maze[curx][cury] && maze[curx][cury]<=''){
//如果当前位置有怪物
int t; //怪物的HP
t=maze[curx][cury]-'';
for(int i=;i<=t;i++){
way[s-i].x=curx;
way[s-i].y=cury;
way[s-i].ism=true;
}
}
else{
//当前位置没有怪物
way[s].x=curx;
way[s].y=cury;
way[s].ism=false;
}
return s;
}
//没有走到终点的时候
for(int i=;i<;i++){
int nx = curx+dx[i];
int ny = cury+dy[i];
if(<=nx && nx<=N- && <=ny && ny<=M- //如果没有越界
&& maze[nx][ny]!='X' //下一步没有陷阱
&& !isv[nx][ny] //下一步没走过
){
int t; //有怪物的话存储怪物的HP,否则为1
if(''<=maze[nx][ny] && maze[nx][ny]<=''){
t=int(maze[nx][ny]-'')+;
}
else{
t=;
}
if(s+t>=_min) continue; //再次剪枝
isv[nx][ny]=true;
int tt;
if( tt=dfs(nx,ny,s+t) ){
//找到最短路
n=tt;
way[s].x=curx;
way[s].y=cury;
way[s].ism=false;
if(''<=maze[curx][cury] && maze[curx][cury]<=''){
//如果当前位置有怪物
int t; //怪物的HP
t=maze[curx][cury]-'';
for(int i=;i<=t;i++){
way[s-i].x=curx;
way[s-i].y=cury;
way[s-i].ism=true;
}
}
}
isv[nx][ny]=false;
}
}
return n;
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF){ //开始一个新的地图
getchar();
memset(isv,,sizeof(isv)); //初始化
_min=;
curx=,cury=; //初始化开始、终点位置
endx=N-,endy=M-;
for(int i=;i<N;i++){
for(int j=;j<M;j++){
scanf("%c",&maze[i][j]);
}
getchar();
}
int n; //如果能走到终点的话,接收最短步数
isv[][]=true;
n=dfs(curx,cury,);
if(n){
//能走
printf("It takes %d seconds to reach the target position, let me show you the way.\n",n);
for(int i=;i<n;i++){
if(way[i].ism){
//如果有怪物
printf("%ds:FIGHT AT (%d,%d)\n",i+,way[i].x,way[i].y);
}
else {
printf("%ds:(%d,%d)->(%d,%d)\n",i+,way[i].x,way[i].y,way[i+].x,way[i+].y);
}
}
}
else{
//走不到终点
printf("God please help our poor hero.\n");
}
printf("FINISH\n");
}
return ;
}
2014/1/16 22:51:00
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
char a[][]; //记录地图
char b[][]; //备用地图,用以修改
int isv[][]; //记录访问过没有
int way[][]; //记录路径
int dx[] = {,,,-};
int dy[] = {,,-,};
int N,M;
struct NODE{
int x;
int y;
int step;
};
bool judge(int x,int y)
{
if( x< || y< || x>N || y>M ) //出界
return ;
if( isv[x][y] ) //走过
return ;
if( a[x][y]=='X' ) //遇到墙
return ;
return ;
}
int bfs(int x,int y) //返回到达终点的时间(包括在终点停留的时间)
{
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
b[i][j] = a[i][j];
queue <NODE> q;
NODE cur,next;
cur.x = x;
cur.y = y;
cur.step = ;
q.push(cur); //第一个节点入队
while(!q.empty()){
cur = q.front();
q.pop(); //队首出队
if( cur.x==N && cur.y==M ){
int num = ;
if(''<=b[cur.x][cur.y] && b[cur.x][cur.y]<='')
num = b[cur.x][cur.y] - '';
return cur.step + num;
}
if(''<=b[cur.x][cur.y] && b[cur.x][cur.y]<=''){ //遇到怪物,step+1,位置不变,入队
next.x = cur.x;
next.y = cur.y;
next.step = cur.step + ;
q.push(next);
if(b[cur.x][cur.y]=='')
b[cur.x][cur.y] = '.';
b[cur.x][cur.y]--;
continue;
}
for(int i=;i<;i++){
int nx = cur.x + dx[i];
int ny = cur.y + dy[i];
if(judge(nx,ny)) //判定
continue;
//可以走
next.x = nx;
next.y = ny;
way[nx][ny] = i; //记录路径
isv[nx][ny] = true; //记录访问过
next.step = cur.step + ;
q.push(next);
}
}
return ;
}
int main()
{
while(cin>>N>>M){
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
cin>>a[i][j];
memset(isv,,sizeof(isv));
isv[][] = true;
int step = bfs(,);
if(step){ //到达终点
NODE way_node[];
int cx=N,cy=M;
for(int i=step;i>=;i--){ //根据way[][]还原路径
way_node[i].x = cx;
way_node[i].y = cy;
int num=;
if(''<=a[cx][cy] && a[cx][cy]<='') //如果该位置有怪物
num = a[cx][cy] - '';
for(int j=num;j>=;j--){
way_node[i-j].x = cx;
way_node[i-j].y = cy;
}
if(num){
i-=num;
}
switch(way[cx][cy]){ //没有怪物则继续还原路径
case :cy--;break;
case :cx--;break;
case :cy++;break;
case :cx++;break;
default:break;
}
}
//输出结果
cout<<"It takes "<<step<<" seconds to reach the target position, let me show you the way."<<endl;
for(int i=;i<=step;i++){
cout<<i<<"s:("<<way_node[i-].x-<<','<<way_node[i-].y-<<")->("<<way_node[i].x-<<','<<way_node[i].y-<<')'<<endl;
cx = way_node[i].x;
cy = way_node[i].y;
if(''<=a[cx][cy] && a[cx][cy]<=''){
int num = a[cx][cy] - '';
for(int j=;j<=num;j++)
cout<<i+j<<"s:FIGHT AT ("<<way_node[i].x-<<','<<way_node[i].y-<<')'<<endl;
i += num;
}
}
cout<<"FINISH"<<endl;
}
else{ //没有到达终点
cout<<"God please help our poor hero."<<endl;
cout<<"FINISH"<<endl;
}
}
return ;
}
2014-01-18 16:50:53
受同学启发,用“优先队列”又写了一遍,顺便学习了一下优先队列的使用。
思路和上面是基本相同的,只不过遇到怪物时的处理用优先队列简化了许多,优先队列不会用的筒靴可以参考下面的链接:
另外给出一位同样用优先队列实现的博客链接,不过人家是0MS AC,我是31MS AC,有差距啊!
下面是我用优先队列做的代码:
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
char a[][];
char isv[][]; //记录访问过没有
int dir[][]; //记录每一个节点的来路方向,即整个地图遍历的顺序
int dx[] = {,,,-};
int dy[] = {,,-,};
int N,M;
struct NODE{
int x;
int y;
int step;
friend bool operator < (NODE n1,NODE n2) //自定义优先级。在优先队列中,优先级高的元素先出队列。
{
return n1.step > n2.step; //通过题意可知 step 小的优先级高,需要先出队。
}
};
bool judge(int x,int y)
{
if( x< || y< || x>N || y>M )
return ;
if( isv[x][y] )
return ;
if( a[x][y]=='X' )
return ;
return ;
}
int bfs(int x,int y) //返回从(x,y)开始广搜,到右下角的最短步数,如果无法到达右下角,返回0
{
priority_queue <NODE> q; //定义一个优先队列
NODE cur,next;
cur.x = x;
cur.y = y;
cur.step = ;
q.push(cur); //第一个元素入队
while(!q.empty()){
cur = q.top(); //队首出队,注意不是front()
q.pop();
if(cur.x==N && cur.y==M){ //到终点
return cur.step;
}
for(int i=;i<;i++){
int nx = cur.x + dx[i];
int ny = cur.y + dy[i];
if( judge(nx,ny) ) //判定
continue;
//可以走
next.x = nx;
next.y = ny;
isv[nx][ny] = true;
dir[nx][ny] = i;
if( ''<=a[nx][ny] && a[nx][ny]<='' ){ //这一步有怪物
int hp = a[nx][ny] - '';
next.step = cur.step + hp + ;
}
else //这一步没有怪物
next.step = cur.step + ;
q.push(next);
}
}
return ;
}
int main()
{
while(cin>>N>>M){
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
cin>>a[i][j];
memset(isv,,sizeof(isv));
isv[][] = true;
int step = bfs(,);
if(step){ //step有值,能够到达终点
//还原路径
NODE way[];
int cx=N,cy=M;
for(int i=step;i>=;i--){
way[i].x = cx;
way[i].y = cy;
if(''<=a[cx][cy] && a[cx][cy]<=''){ //当前位置有怪物
int hp = a[cx][cy] - '';
for(int j=;j<=hp;j++){
way[i-j].x = cx;
way[i-j].y = cy;
}
i -= hp;
}
switch(dir[cx][cy]){
case :cy--;break;
case :cx--;break;
case :cy++;break;
case :cx++;break;
default:break;
}
}
//输出结果
cout<<"It takes "<<step<<" seconds to reach the target position, let me show you the way."<<endl;
for(int i = ;i<=step;i++){
cout<<i<<"s:("<<way[i-].x-<<','<<way[i-].y-<<")->("<<way[i].x-<<','<<way[i].y-<<')'<<endl;
if( ''<=a[way[i].x][way[i].y] && a[way[i].x][way[i].y]<='' ){ //如果有怪物
int hp = a[way[i].x][way[i].y] - '';
for(int j=;j<=hp;j++)
cout<<i+j<<"s:FIGHT AT ("<<way[i+j].x-<<','<<way[i+j].y-<<')'<<endl;
i+=hp;
}
}
}
else{ //step为0,说明不能到达终点
cout<<"God please help our poor hero."<<endl;
}
cout<<"FINISH"<<endl;
}
return ;
}
Freecode : www.cnblogs.com/yym2013
hdu 1026:Ignatius and the Princess I(优先队列 + bfs广搜。ps:广搜AC,深搜超时,求助攻!)的更多相关文章
- hdu 1026 Ignatius and the Princess I(优先队列+bfs+记录路径)
以前写的题了,现在想整理一下,就挂出来了. 题意比较明确,给一张n*m的地图,从左上角(0, 0)走到右下角(n-1, m-1). 'X'为墙,'.'为路,数字为怪物.墙不能走,路花1s经过,怪物需要 ...
- HDU 1026 Ignatius and the Princess I(BFS+优先队列)
Ignatius and the Princess I Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d &am ...
- hdu 1026 Ignatius and the Princess I(bfs)
Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- HDU 1026 Ignatius and the Princess I (BFS)
题目链接 题意 : 从(0,0)点走到(N-1,M-1)点,问最少时间. 思路 : BFS..... #include <stdio.h> #include <string.h> ...
- hdu 1026 Ignatius and the Princess I(BFS+优先队列)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1026 Ignatius and the Princess I Time Limit: 2000/100 ...
- hdu 1026 Ignatius and the Princess I
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1026 Ignatius and the Princess I Description The Prin ...
- hdu 1026 Ignatius and the Princess I【优先队列+BFS】
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1026 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- hdu 1026 Ignatius and the Princess I (bfs+记录路径)(priority_queue)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1026 Problem Description The Princess has been abducted ...
- hdu 1026 Ignatius and the Princess I 搜索,输出路径
Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
随机推荐
- Android SDK镜像的介绍使用【转发】
由于一些原因,Google相关很多服务都无法访问,所以在很多时候我们SDK也无法升级,当然通过技术手段肯定可以解决,但是比较麻烦,而且下载速度也不怎么样. 这里笔者介绍一个国内的Android镜像站, ...
- 霍炬:再谈百度:KPI、无人机,以及一个必须给父母看的案例
作者:霍炬. 原文链接:http://www.donews.com/idonews/article/8147.shtm 没想到我之前的一篇关于百度的文章引起了这么大的反馈. 非常多朋友称赞我写的好, ...
- OFBiz:处理nextRequestResponse
这里的nextRequestResponse是指RequestHandler中doRequest()函数在最后使用的一个变量,doRequest()会依据nextRequestResponse返回不同 ...
- 优化技术之Android高效开发
基于Android平台的设备一定是嵌入式设备. 两个原则判断一个系统是否合理:不要做不必要做的事情:尽可能地节省内存的使用. 1. 尽量避免创建对象Object 2. 使用自身方法 3. 使用虚拟优于 ...
- [HNOI2002]营业额统计 Splay tree
Splay tree入门题,学好代码风格,学习HH大牛的,传送门.. #include <functional> #include <algorithm> #include & ...
- 前端异步文件上传组件 Uploader
Uploader是非常强大的异步文件上传组件,支持ajax.iframe.flash三套方案,实现浏览器的全兼容,调用非常简单,内置多套主题支持 和常用插件,比如验证.图片预览.进度条等,广泛应用于淘 ...
- EntityFramework Data Annotations
详细的实体映射介绍(Data Annotation) http://msdn.microsoft.com/en-us/data/jj591583
- C# 获取文件MD5、SHA1
/// <summary> /// 计算文件的 MD5 值 /// </summary> /// <param name="fileName"> ...
- HTML5 拖拽的简单实践
坑爹点记录: 1.一定要加入 event.preventDefault(); 不然无效. 2.想测试的话,随便找到一个layui的table演示页面,插入脚本即可.不过要先在全局插入jquery. v ...
- Spring Cloud 模块简介2
前面一篇文章谈到微服务基础框架,而Netflix的多个开源组件一起正好可以提供完整的分布式微服务基础架构环境,而对于Spring Cloud正是对Netflix的多个开源组件进一步的封装而成,同时又实 ...