先預處理出每個點能到的需要建荷花的地方,把中間走的步數省略了,這樣再最短路到終點就是最少需要建的荷花數。
至於方案數,只要把上一個點的方案數加起來就好了。
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
ll dir[8][2]={
2,1,
1,2,
2,-1,
-1,2,
-2,1,
1,-2,
-1,-2,
-2,-1
};
ll m,n;
ll map[50][50];
ll sx,sy,tx,ty;
int d[50][50][50][50];
bool inside(ll x,ll y)
{
if(x>=1&&x<=m&&y>=1&&y<=n)return 1;
return 0;
}
bool met[50][50];
void bfs1(ll x,ll y)
{
memset(met,0,sizeof(met));
queue<int>X;
queue<int>Y;
X.push(x);
Y.push(y);
met[x][y]=1;
while(!X.empty())
{
ll ux=X.front();
ll uy=Y.front();
X.pop();
Y.pop();
for(ll i=0;i<8;i++)
{
ll xx=ux+dir[i][0];
ll yy=uy+dir[i][1];
if(inside(xx,yy))
{
if(met[xx][yy]==0)
{
met[xx][yy]=1;
if(map[xx][yy]==1)
{
X.push(xx);
Y.push(yy);
}else
{
d[x][y][xx][yy]=1;
}
}
}
}
}
}
ll ans[50][50];
ll dis[50][50];
ll len[50][50];
void bfs2()
{
memset(ans,0,sizeof(ans));
memset(dis,0x3f,sizeof(dis));
queue<int>X;
queue<int>Y;
X.push(sx);
Y.push(sy);
ans[sx][sy]=1;
dis[sx][sy]=0;
len[sx][sy]=0;
while(!X.empty())
{
ll ux=X.front();
ll uy=Y.front();
X.pop();
Y.pop();
if(map[ux][uy]==2)continue;
for(ll i=1;i<=m;i++)
{
for(ll j=1;j<=n;j++)
{
if(d[ux][uy][i][j])
{
if(dis[i][j]==dis[ux][uy]+1)
{
ans[i][j]+=ans[ux][uy];
}else if(dis[i][j]>dis[ux][uy]+1)
{
dis[i][j]=dis[ux][uy]+1;
ans[i][j]=ans[ux][uy];
X.push(i);
Y.push(j);
}
}
}
}
}
}
int main()
{
while(scanf("%lld %lld",&m,&n)!=EOF)
{
for(ll i=1;i<=m;i++)
{
for(ll j=1;j<=n;j++)
{
scanf("%lld",&map[i][j]);
if(map[i][j]==3)
{
sx=i;
sy=j;
}
if(map[i][j]==4)
{
tx=i;
ty=j;
}
}
}
memset(d,0,sizeof(d));
for(ll i=1;i<=m;i++)
{
for(ll j=1;j<=n;j++)
{
bfs1(i,j);//預處理
}
}
bfs2();
if(dis[tx][ty]>25000)
{
printf("-1\n");
}else
{
printf("%lld\n%lld\n",dis[tx][ty]-1,ans[tx][ty]);
}
}
return 0;
}
usacoSilver Lilypad Pond, 2007 Feb