题目描述
为了拯救沦陷的CSU,PIPI不得不打怪升级。
已知PIPI的修炼场是个n*m的区域,区域内的每块地方都会有怪物刷新,但是怪物只会存在刷新的这一秒。当PIPI所在的格子正好刷新出怪物时,PIPI会立马打死他并获得1经验值。PIPI零秒时在修炼场的位置为(sx,sy),且只能在位置为(ex,ey)的地方离开修炼场。同时,PIPI每秒可以向上/下/左/右四个方向移动一格或者待在原地不动,而PIPI打怪则不消耗任何时间。 PIPI决定离开修炼场时的经验值必须大于等于c,请问PIPI最少花多少时间才能离开修炼场。
PS:若到达终点那一秒正好刷新了怪物,打死后经验值又正好大于等于c,可以立马离开。
输入
第一行输入三个正整数n,m,c,其中n,m<=50,c<=100。
接下来n行,每行m个正整数Aij(Aij<=10),表示在位置(i,j)处,每过Aij秒会刷新怪物。也就是说,假如PIPI第k(k>0)秒在(i,j)上,且满足k是Aij的倍数,则PIPI会打死刷新的怪物并获得1经验值。怪物会无数次刷新,不会打死后该位置就再也没有怪物了。
最后一行输入四个正整数,sx,sy,ex,ey,其中sx,ex<=n,sy,ey<=m。
输出
输出PIPI离开修炼场的最少时间。
样例输入
1 3 2
1 2 3
1 1 1 3
样例输出
3
思路:题中要同时兼顾两个条件,一是要时间最短,其次是经验值要大于等于c,乍一看不知从何下手,其实只需要把状态定义为多维,这里的状态定义为坐标、时间、经验值,vis数组可以定义为vis[55][55][12][105],其中第三维指的是当前点距离刷新的时间,这样就把所以的状态都列举出来了,然后直接bfs搜索
#include<bits/stdc++.h>
using namespace std;
int dir[][2]={0,0,1,0,-1,0,0,1,0,-1};
bool vis[55][55][12][105];
int mp[55][55];
struct node{
int x,y,ti,k; ///ti值的是总共经过的时间,k是此时的经验值
}t;
int sx,sy,ex,ey;
int n,m,c;
void bfs(int sx,int sy){
queue<node> q;
q.push({sx,sy,0,0});
vis[sx][sy][0][0]=1;
while(q.size()){
node now=q.front();q.pop();
if(now.x==ex&&now.y==ey&&now.k>=c){
printf("%d",now.ti);
return;
}
for(int i=0;i<5;i++){
int xx=now.x+dir[i][0];
int yy=now.y+dir[i][1];
if(xx<0||xx>=n||yy<0||yy>=m) continue;
if((now.ti+1)%mp[xx][yy]==0&&!vis[xx][yy][0][now.k+1]){///此时刚好有怪兽出来,经验值加一
t.x=xx,t.y=yy,t.ti=now.ti+1,t.k=now.k+1;
q.push(t);
vis[xx][yy][0][t.k]=1;
}else if((now.ti+1)%mp[xx][yy]!=0&&!vis[xx][yy][(now.ti+1)%mp[xx][yy]][now.k]){///没有怪兽
t.x=xx,t.y=yy,t.ti=now.ti+1,t.k=now.k;
q.push(t);
vis[xx][yy][t.ti%mp[xx][yy]][t.k]=1;
}
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&c);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%d",&mp[i][j]);
}
}
scanf("%d%d%d%d",&sx,&sy,&ex,&ey),sx--,sy--,ex--,ey--;
bfs(sx,sy);
}