题意:从1,1走到n,m,途中有.\*\#三种符号,#表示不能走过去.表示可以走过去,但需要消耗1体力,*表示弹射,从这个点走过去不消耗体力,且可以四个方向弹射x的距离。
分析:用堆优化的bfs写,每次把通过出队的点去更新其他点,出队的点被标记,表示从这个点已经走过去了,以后不能再走,这样为什么是最优的,因为每次被更新的点加进去之后,出对之后一定是最小的,所以要标记出队的点,而不是每次入队的点,都要标记。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef long long LL;
const int N = 3010;
typedef pair<int,pair<int,int>> PII;
int g[N][N];
//int n;
bool st[N][N];
int tx[5]={-1,0,1,0},ty[5]={0,1,0,-1};
int n,m;
char s[N][N];
priority_queue<PII,vector<PII>,greater<PII>> q;
int dij()
{
q.push({0,{1,1}});
while(q.size())
{
auto t=q.top();
q.pop();
int cnt=t.x,x1=t.y.x,y1=t.y.y;
if(st[x1][y1]) continue;
st[x1][y1]=true;
if(x1==n&&y1==m) return cnt;
for(int i=0;i<4;i++)
{
int a,b;
int k;
if(s[x1][y1]=='.')
{
k=1;
a=x1+tx[i],b=y1+ty[i];
}
else if(s[x1][y1]=='*')
{
k=0;
a=x1+tx[i]*g[x1][y1],b=y1+ty[i]*g[x1][y1];
}
else continue;
if(a<=0||a>n||b<=0||b>m) continue;
q.push({k+cnt,{a,b}});
}
}
return -1;
}
void solve()
{
cin>>n>>m;
// getchar();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>s[i][j];
int z;
cin>>z;
while(z--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=c;
}
int k=dij();
if(k==-1) cout<<-1<<endl;
else cout<<k<<endl;
}
signed main()
{
IOS;
// int t;
// cin>>t;
// while(t--)
solve();
return 0;
}