大水题
就是双优先级Spfa加图论建边
说的感觉好高大上啊~
有个神奇的PPT
https://yunpan.cn/ckDHaKvcxV4ne 访问密码 5bab
题目描述 Description
在一个n*m的一个方块阵阵地上仅由楼房和街道组成,现在你在(x1,y1)点,伤员在(x2,y2)点,你可以向周围的8个方向移动,也可以爬上一部分楼房。而伤员因为受了伤,动弹不得,你必须背他回来。因此你所最担心的不是你的路程长短,而是你在救援中费的力气的大小。你爬上一幢高为H的楼房,或者从高为H的楼房房顶下来,都需要花费H的力气,而没有高度落差的行走是不费力的。现在你要完成救援的任务,最少要花费多少力气呢?费力最小的情况下,你最少又要走多少路呢?这里上、下楼不算走路。
输入描述 Input Description
输入文件的第1行有两个正整数n,m(n,m<=500),第2,3行分别是(x1,y1),(x2,y2)(1<=x1,x2<=n,1<=y1,y2<=m)。接下来有n行,每行m个数,第I行,第J列为1表示此处为空地,为2表示此处为房顶,为0表示此处无法攀爬。保证起点,终点不在0上,你可以假设可攀爬的楼房高度都为1。你到了(x2,y2)就表示救援成功。
输出描述 Output Description
输出文件包括两个在一行的数x,y,用一个空格隔开。X表示费力最少的情况下,路径的最短长度,Y表示最少花费的力气量。若无法完成营救任务,则输出’0 0’(引号不输出)。
样例输入 Sample Input
3 7
1 1
3 7
2100212
2121010
2221012
样例输出 Sample Output
8 4
数据范围及提示 Data Size & Hint
30%的数据满足:n,m<=10
100%的数据满足:n,m<=500
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int x,y,c,next;
}a[21000000];int len,first[2500000];
bool v[2500000];
int dx[9]={0,1,-1,0,0,-1,-1,1,1};
int dy[9]={0,0,0,-1,1,-1,1,-1,1};
int n,m,stx,sty,edx,edy,d[2500000],dd[2500000],head,tail,list[2500000],map[510][510];
void ins(int x,int y,int c){
len++;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=first[x];first[x]=len;
}
void spfa(int st,int ed){
memset(v,false,sizeof(v));v[st]=true;
memset(d,63,sizeof(d));d[st]=0;d[ed]=999999999;
memset(dd,63,sizeof(dd));dd[st]=0;dd[ed]=999999999;
head=1;tail=2;list[head]=st;
while(head!=tail){
int x=list[head];
for(int k=first[x];k>0;k=a[k].next){
int y=a[k].y;
if(d[y]>=d[x]+a[k].c){
if(d[y]==d[x]+a[k].c){
if(dd[y]>dd[x]+1){
dd[y]=dd[x]+1;
if(v[y]==false){
v[y]=true;
list[tail++]=y;if(tail==n*m+1)tail=1;
}
}
}
else{
d[y]=d[x]+a[k].c;
dd[y]=dd[x]+1;
if(v[y]==false){
v[y]=true;
list[tail++]=y;if(tail==n*m+1)tail=1;
}
}
}
}
v[x]=false;
head++;if(head==n*m+1)head=1;
}
}
int main(){
scanf("%d%d",&n,&m);
scanf("%d%d%d%d",&stx,&sty,&edx,&edy);
char s[510];
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++){
map[i][j]=s[j]-'0';
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(map[i][j]==0)continue;
for(int k=1;k<=8;k++){
int fx=i+dx[k],fy=j+dy[k];
if(fx>=1&&fx<=n&&fy>=1&&fy<=m&&map[fx][fy]!=0){
ins((i-1)*m+j,(fx-1)*m+fy,abs(map[i][j]-map[fx][fy]));
}
}
}
}
spfa((stx-1)*m+sty,(edx-1)*m+edy);
if(d[(edx-1)*m+edy]==999999999)printf("0 0\n");
else printf("%d %d\n",dd[(edx-1)*m+edy]+1,d[(edx-1)*m+edy]);
return 0;
}