和bzoj同名题不一样!
起点和水点向花费一个荷花能到的第一个点连一条边权为1的有向边,然后跑计数spfa即可
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=35,dx[]={-1,-1,1,1,-2,-2,2,2},dy[]={-2,2,-2,2,-1,1,-1,1};
int n,m,a[N][N],id[N][N],tot,h[N*N],cnt,s,t,dis[N*N],vis[N][N],ti;
long long b[N*N];
bool v[N*N];
struct qwe
{
int ne,to;
}e[500005];
void add(int u,int v)
{//cerr<<u<<" "<<v<<endl;
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
h[u]=cnt;
}
inline bool ok(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m&&a[x][y]!=2&&vis[x][y]!=ti;
}
void dfs(int u,int x,int y,int f)
{//cerr<<u<<" "<<x<<" "<<y<<endl;
vis[x][y]=ti;
if((a[x][y]==4||a[x][y]==0)&&!f)
{
add(u,id[x][y]);
// add(id[x][y],u);
return;
}
for(int i=0;i<8;i++)
if(ok(x+dx[i],y+dy[i]))
dfs(u,x+dx[i],y+dy[i],0);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
id[i][j]=++tot;
if(a[i][j]==3)
s=id[i][j];
if(a[i][j]==4)
t=id[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]!=2&&a[i][j]!=1)
ti++,dfs(id[i][j],i,j,1);
queue<int>q;
for(int i=1;i<=tot;i++)
dis[i]=1e9;
dis[s]=0;
b[s]=1;
v[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
v[u]=0;
for(int i=h[u];i;i=e[i].ne)
{
if(dis[e[i].to]>dis[u]+1)
{
dis[e[i].to]=dis[u]+1;
b[e[i].to]=b[u];
if(!v[e[i].to])
{
v[e[i].to]=1;
q.push(e[i].to);
}
}
else if(dis[e[i].to]==dis[u]+1)
{
b[e[i].to]+=b[u];
if(!v[e[i].to])
{
v[e[i].to]=1;
q.push(e[i].to);
}
}
}
}
if(dis[t]==1e9)
puts("-1");
else
printf("%d
%lld
",dis[t]-1,b[t]);
return 0;
}