2018北大暑校acm算法训练课程 鸣人与佐助 三维搜索

佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢?
已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大蛇丸的手下才能到这些位置。鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,每移动一个距离需要花费1个单位时间,打败大蛇丸的手下不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人要追上佐助最少需要花费多少时间?
Input
输入的第一行包含三个整数:M,N,T。代表M行N列的地图和鸣人初始的查克拉数量T。0 < M,N < 200,0 ≤ T < 10 
后面是M行N列的地图,其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下。
Output
输出包含一个整数R,代表鸣人追上佐助最少需要花费的时间。如果鸣人无法追上佐助,则输出-1。
Sample Input
样例输入1
4 4 1
#@##
**##
###+
****

样例输入2
4 4 2
#@##
**##
###+
****
Sample Output
样例输出1
6

样例输出2
4

题解:该题不难想象是一个搜索问题,求最短时间即用bfs求解即可
(本人解法为开三维数组记录到某点剩余查克拉数量的解法,可能有其他解法)
本题中没有墙壁的限制,但是大蛇丸的手下相当于是墙壁,即鸣人可以穿过T个墙以缩短他的寻找时间,这就使得原有的二维标记数组成了摆设.
我们可以假设这样一种情况:

2018北大暑校acm算法训练课程 鸣人与佐助 三维搜索_第1张图片
假设我们的地图是上图中图1的样子
数据为:3 6 1
那么从图中很容易看出我们要将鸣人唯一的查克拉用在对(2,6)的敌人身上
我们正确答案的寻找路径应为:
(1,1)->(2,1)->(3,1)->(3,2)->(3,3)->(2,3)->(1,3)->(1,4)->(1,5)->(1,6)->(2,6)->(3,6)
一共11步
但是如果我们只看(1,3)该点来说,在我们只开二维数组的情况下,他的最短距离是2,即使用一个查克拉干掉(1,2)这个敌人后直接走到了(1,3),但是很明显在这里用了查克拉后我们就无法到达鸣人那里,很遗憾.
故按照平常我们只开二维数组标记每个走过的点会导致本题的答案错误.
如何解决?
开一个三维数组,标记到达每一个点的查克拉的数目,这样尽管增加了空间,但是查克拉的范围是0-10,N和M的范围都在200,这就说明我们最多开一个400000的标记数组,还是能够接受的,同时bfs可以保证一旦我们到达佐助的位置一定是最小值(原因此处省略)

本人代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MAX_N=100000;
const int INF = 0x3f3f3f3f;
#define eps 1e-7
//#define Kongxiangzhouye

char maps[300][300];
int vis[300][300][20];
int n,m,t;
struct p{
    int x;
    int y;
    int step;
    int ckl;
};
int wsad[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int bfs(p tem){
    queue

q; q.push(tem); vis[tem.y][tem.x][tem.ckl]=1; while(!q.empty()){ p now=q.front(); q.pop(); // cout< if(maps[now.y][now.x]=='+') return now.step; for(int i=0;i<4;i++){ p next=now; next.x=now.x+wsad[i][0]; next.y=now.y+wsad[i][1]; if(next.x<0||next.x>=m||next.y<0||next.y>=n) continue; if(maps[next.y][next.x]=='#'){ if(next.ckl>=1) next.ckl--; else continue; } next.step+=1; if(vis[next.y][next.x][next.ckl]==1) continue; q.push(next); vis[next.y][next.x][next.ckl]=1; } } return -1; } p st; int main(){ ios::sync_with_stdio(false); #ifdef Kongxiangzhouye freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif cin>>n>>m>>t; memset(vis,0,sizeof(vis)); for(int i=0;ifor(int j=0;jcin>>maps[i][j]; } } for(int i=0;ifor(int j=0;jif(maps[i][j]=='@'){ st.ckl=t; st.step=0; st.x=j; st.y=i; break; } } } cout<return 0; }

你可能感兴趣的:(pku_acm)