起点和终点将矩阵分成两部分,然后让你从两个部分分别求一条最短路。
判断点属于那个部分只要用ToLeftTest就可以了,大于0在直线的左边。第一次求起点到终点,第二次求终点到起点的最短路。起点和终点的分数这样会被计算两次,需要减一下。
#include
using namespace std;
int n,m,inq[120][120];
double s[120][120];
double d[120][120];
int dx[]= {1,-1,0,0,1,-1,1,-1};
int dy[]= {0,0,1,-1,1,-1,-1,1};
struct Point
{
int x;
int y;
};
int cross(const Point &a, const Point &b, const Point &p)
{
return (b.x - a.x)*(p.y - a.y) - (b.y - a.y)*(p.x - a.x);
}
int toLeft(const Point &a, const Point &b, const Point &p)
{
return cross(a, b, p);
}
double spfa1(int sx,int sy,int ex,int ey)
{
for(int i=0; i<100; i++)
for(int j=0; j<100; j++)
{
inq[i][j]=0;
d[i][j]=1e10;
}
Point a,b,p;
a.x=sx;
a.y=sy;
b.x=ex;
b.y=ey;
d[sx][sy]=s[sx][sy];
queue<int>qx;
queue<int>qy;
qx.push(sx);
qy.push(sy);
while(!qx.empty())
{
int x=qx.front();
int y=qy.front();
qx.pop();
qy.pop();
inq[x][y]=0;
for(int i=0; i<8; i++)
{
double w=0;
int tx=x+dx[i];
int ty=y+dy[i];
if(tx<0||tx>=n||ty<0||ty>=m) continue;
p.x=tx;
p.y=ty;
if(toLeft(a,b,p)>0||(tx==ex&&ty==ey))
{
//if(s[tx][ty]<0) continue;
w=s[tx][ty];
if(i>3) w=w+(s[x][y]+s[tx][ty])*(sqrt(2)-1);
if(d[tx][ty]>d[x][y]+w)
{
d[tx][ty]=d[x][y]+w;
if(inq[tx][ty]==0)
{
qx.push(tx);
qy.push(ty);
inq[tx][ty]=1;
}
}
}
}
}
return d[ex][ey];
}
int main()
{
cin>>n>>m;
for(int i=0; ifor(int j=0; jcin>>s[i][j];
}
}
int sx,sy,ex,ey;
cin>>sy>>sx>>ey>>ex;
//cin>>sx>>sy>>ex>>ey;
/*
int a=__gcd(abs(sx-ex),abs(sy-ey));
int bx=abs(sx-ex)/a;
int by=abs(sy-ey)/a;
int nx,ny;
nx=sx+bx;
ny=sy+by;
while(1)
{
if(nx<0||ny<0||nx>=n||ny>=m) break;
//printf("%d %d\n",nx,ny);
if(nx==sx&&ny==sy)
{
nx+=bx;
ny+=by;
continue;
}
if(nx==ex&&ny==ey)
{
nx+=bx;
ny+=by;
continue;
}
s[nx][ny]=-1;
nx+=bx;
ny+=by;
}
nx=sx-bx;
ny=sy-by;
while(1)
{
if(nx<0||ny<0||nx>=n||ny>=m) break;
//printf("%d %d\n",nx,ny);
if(nx==sx&&ny==sy)
{
nx-=bx;
ny-=by;
continue;
}
if(nx==ex&&ny==ey)
{
nx-=bx;
ny-=by;
continue;
}
s[nx][ny]=-1;
nx-=bx;
ny-=by;
}*/
printf("%.2f\n",spfa1(sx,sy,ex,ey)+spfa1(ex,ey,sx,sy)-s[sx][sy]-s[ex][ey]);
return 0;
}