0910 OpenJ#6044 鸣人和佐助

摘要
-使用bfs来寻找最短的可行路径
原题目摘要
-鸣人和佐助

-

佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢?


已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大蛇丸的手下才能到这些位置。鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,每移动一个距离需要花费1个单位时间,打败大蛇丸的手下不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人要追上佐助最少需要花费多少时间?

输入
输入的第一行包含三个整数:M,N,T。代表M行N列的地图和鸣人初始的查克拉数量T。0 < M,N < 200,0 ≤ T < 10
后面是M行N列的地图,其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下。
输出
输出包含一个整数R,代表鸣人追上佐助最少需要花费的时间。如果鸣人无法追上佐助,则输出-1。
样例输入
样例输入
14 4 1
#@##**
#####+
****
样例输入2

4 4 2
#@##**
#####+
****

样例输出
样例输出16样例输出24


题目理解
-设置每个位置查克拉的数量不同为不同的状态,用三维数组标记。然后开始bfs。类似的最路径问题如果需要记录路径的话  要用于状态数相同的对应数组保存当前位置状态的来源。找到目的状态后,用一个栈就可以向回访问到起点。输出栈记为路径。
注意
-刚开始没有注意到到一个点可以有多种途径。查克拉成为了一个状态的附加状态。因此只能将同一个点不同的查克拉数作为一个状态
日期
-2017 9 10
附加
-
代码
-
#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <cstdio>
#include <cstring>
#include <set>
#include <queue>

using namespace std;
#define MAX 205

struct Node{
    int x,y,t,step;
    Node(){x=y=step=t=-1;}
    Node(int _x,int _y,int _t,int _s):x(_x),y(_y),t(_t),step(_s){}
};

bool vis[MAX][MAX][11];//is vis?
char M[MAX][MAX];
int m,n,T;
queue< Node > q;

bool check(int x,int y){
    return  x>=0
        && x<m
        && y>=0
        && y<n;
}

int dx[]={-1,0,1,0},dy[]={0,-1,0,1};
void dis(){
    Node &node = q.front();
    int dt=0;int tx,ty,tt;//next x,y
    for(int i=0;i<4;i++){
        tx=node.x+dx[i];ty=node.y+dy[i];tt=node.t;
        if(check(tx,ty)){
            dt= M[tx][ty]=='#'?-1:0;
            if(tt+dt>-1 && !vis[tx][ty][tt+dt]){
                q.push(Node(tx,ty,tt+dt,node.step+1));
                vis[tx][ty][node.t+dt]=true;
            }
        }
    }
}

void solve(int bx,int by){
   {
        Node n;
        n.x = bx;n.y = by;n.t = T; n.step = 0;
        q.push(n);vis[n.x][n.y][n.t]=true;
   }
    while(!q.empty()){
        Node &node = q.front();
        if(M[node.x][node.y]=='+'){
            printf("%d\n",node.step);
            return;
        }
        dis();
        q.pop();
    }
    printf("-1");
}


void get_in(){
    bool STATE = false;
    scanf("%d%d%d",&m,&n,&T);
    int bx,by;
    for(int i=0;i<m;i++){
        scanf("%s",M[i]);
        if(!STATE)if(strchr(M[i],'@')!=NULL){STATE=true;
            bx=i;by=(strchr(M[i],'@')-M[i])/sizeof(char);
            }
    }
    memset(vis,false,sizeof(vis));
    solve(bx,by);
}
int main(){
    freopen("in","r",stdin);
    get_in();
    return 0;
}


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值