题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1780
思路:前者可以直接用dijstra算法求出,后者是一个简单的变形。可以将每个点“拆分“成4个不同方向的点,然后用dijstra求出。
#include<cstdio>
#include<queue>
#include<iostream>
#include<vector>
#include<map>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<stack>
#include<algorithm>
#define cle(a) memset(a,0,sizeof(a))
#define inf(a) memset(a,0x3f,sizeof(a))
#define ll long long
#define Rep(i,a,n) for(int i=a;i<=n;i++)
using namespace std;
const int INF = ( 2e9 ) + 2;
const ll maxn = 510;
int mp[maxn][maxn];
int d[maxn][maxn][4];
int vis[maxn][maxn];
int Move[]= {1,0,-1,0,1};
int n,m,r1,c1,r2,c2;
struct node
{
int x,y;
int d;
bool operator < (const node &b)const
{
return this->d>b.d;
}
};
struct dot
{
int x,y,dir;
int d;
bool operator < (const dot &b)const
{
return this->d>b.d;
}
};
bool check(int dx,int dy)
{
return dx>=1&&dx<=n&&dy>=1&&dy<=m;
}
void dijstra2() // 从起点开始
{
priority_queue<dot> q;
q.push(dot{r1,c1,-1,mp[r1][c1]});
while(!q.empty())
{
dot a=q.top();q.pop();
int x= a.x,y=a.y,dis=a.d,dir=a.dir;
// cout<<x<<" "<<y<<" "<<dir<<" "<<dis<<endl;
for(int i=0; i<4; i++)
{
int dx=x+Move[i];
int dy=y+Move[i+1];
if(dir==i)continue;
if(check(dx,dy)&&mp[dx][dy]!=-1&&d[dx][dy][i]>dis+mp[dx][dy])
{
d[dx][dy][i]=dis+mp[dx][dy];
q.push(dot{dx,dy,i,d[dx][dy][i]});
}
}
}
}
void dijstra()
{
priority_queue<node> q;
q.push(node {r2,c2,mp[r2][c2]});
vis[r2][c2]=mp[r2][c2];
while(!q.empty())
{
node a= q.top();
q.pop();
int x=a.x,y=a.y,d=a.d;
for(int i=0; i<4; i++)
{
int dx=x+Move[i];
int dy=y+Move[i+1];
if(check(dx,dy)&&mp[dx][dy]!=-1&&vis[dx][dy]>d+mp[dx][dy])
{
vis[dx][dy]=mp[dx][dy]+d;
q.push(node {dx,dy,vis[dx][dy]});
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
int Cas=0;
while(~scanf("%d%d%d%d%d%d",&n,&m,&r1,&c1,&r2,&c2))
{
char s[20];
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
int temp;
scanf("%s",s);
if(s[0]=='*')
mp[i][j]=-1;
else
{
sscanf(s,"%d",&temp);
mp[i][j]=temp;
}
}
inf(d);
inf(vis);
dijstra();
dijstra2();
int ans=INF;
for(int i=0;i<4;i++)if(ans>d[r2][c2][i])ans=d[r2][c2][i];
if(ans==1061109567)ans=-1;
if(vis[r1][c1]==1061109567)vis[r1][c1]=-1;
cout<<"Case "<<++Cas<<": ";
cout<<vis[r1][c1]<<" ";
cout<<ans<<endl;
}
}