[bzoj 1698] [Usaco 2007 Feb] Lilypad Pond Lotus Leaf Pond

Keywords: REST

Description

Farmer JOHN added a beautiful pond to his farm for cattle to enjoy and exercise. JOHN's pond is a rectangle, and he has divided it into small square rows of M rows and N rows (1 <= M <= 30; 1 <= N <= 30). Some of the square rows are stones, others are particularly strong lotus leaves, and the rest are only clear water. To exercise, Bessie wants to jump from one lotus leaf to another. Every time she jumps, she's a horse's step in chess: two rows, one column, one row, two columns. JOHN saw Bessie and found that sometimes Bessie couldn't reach her target lotus leaf. He's going to add some lotus leaves to let Bessie accomplish her goal. Of course, lotus leaves should not be placed on stones. Help JOHN find out how many lotus leaves he has to put at least and how many plans he has to put at least one lotus leaf in total.

Input

Line 1: Two integers, M and N.

Lines 2-M+1: Line i+1 contains N numbers, which are N lattices of line i, respectively. 0 means that the lattice is empty, 1 means that there is a lotus leaf, 2 means that there are stones in the lattice, 3 means that the lattice is the starting point of Bessie, and 4 means that the lattice is the goal of Bessie.

Output

Line 1: Number of lotus leaves to be added at least. If no solution exists, output - 1.

Line 2: One number, the total number of solutions that reach the minimum. This number is guaranteed not to exceed the size of the built-in 64-bit integer (long / int64). If the first line is - 1, do not output this line.

Sample Input

4 5

1 0 0 0 0

3 0 0 0 0

0 0 2 0 0

0 0 0 4 0

Input Explanation:

The pond contains four rows and five rows. Bessie is in line 2, column 1, and wants to jump to line 4, column 4. There is a piece in the pond.

Stone and three lotus leaves.

Sample Output

2

3

Output interpretation:

At least two lotus leaves are needed. There are three pendulums:

Row 4, column 2, row 2, column 3

Row 1, column 3, row 3, column 2

Row 1, column 3, row 2, column 5



      R1C2,R2C3     R1C3,R3C2     R1C3,R2C5

      1 0 0 0 0     1 0 X 0 0     1 0 X 0 0

      3 0 X 0 0     3 0 0 0 0     3 0 0 0 X

      0 0 2 0 0     0 X 2 0 0     0 0 2 0 0

      0 X 0 4 0     0 0 0 4 0     0 0 0 4 0

Title Solution
For each point 0, search in eight directions, then search for point 0 and connect it with a cost-1 edge. If you search for point 1, continue to search until you find point 0 and cost-1 edge. In this way, for the first question, the shortest path is obtained directly, and for the second question, the number of shortest paths is calculated when the shortest path is obtained.

Code

#include<bits/stdc++.h>
#define inf 1000000
#define N 150005
#define M 1000005
#define ll long long
const int xx[8]={1,1,-1,-1,2,2,-2,-2},yy[8]={2,-2,2,-2,1,-1,1,-1};
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int tot,ret[M],Next[M],len[M],Head[N];
int n,m,a[55][55],S,T;
bool vis[55][55],flag[N];
ll ans[N];int dis[N];
struct node{int x,y;};
inline void ins(int u,int v,int l)
{
    ret[++tot]=v;len[tot]=l;
    Next[tot]=Head[u];Head[u]=tot;
}
int num(int x,int y){return (x-1)*m+y;}
void bfs(int s,int t)
{
    memset(vis,0,sizeof(vis));queue<node>q;
    q.push((node){s,t});vis[s][t]=1;
    while (!q.empty())
    {
        int nx=q.front().x,ny=q.front().y;q.pop();
        for (int i=0;i<8;i++)
        {
            int x=nx+xx[i],y=ny+yy[i];
            if (x<1||x>n||y<1||y>m||a[x][y]==2||vis[x][y]) continue;
            vis[x][y]=1;
            if (a[x][y]==0) ins(num(s,t),num(x,y),1);
            if (a[x][y]==4) ins(num(s,t),num(x,y),0);
            if (a[x][y]==1) q.push((node){x,y});
        }
    }
}
void spfa()
{
    for (int i=1;i<=n*m;i++) dis[i]=inf;
    queue<int>q;
    q.push(S);dis[S]=0;flag[S]=1;ans[S]=1LL;
    while (!q.empty())
    {
        int now=q.front();q.pop();
        for (int i=Head[now];i;i=Next[i])
        {
            if (dis[ret[i]]>dis[now]+len[i])
            {
                dis[ret[i]]=dis[now]+len[i];
                ans[ret[i]]=ans[now];
                if (!flag[ret[i]])flag[ret[i]]=1,q.push(ret[i]);
            }
            else if (dis[ret[i]]==dis[now]+len[i])
            {
                ans[ret[i]]+=ans[now];
                if (!flag[ret[i]])flag[ret[i]]=1,q.push(ret[i]);

            }
        }

        flag[now]=0;
    }
}
int main()
{
    n=read();m=read();
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            a[i][j]=read();
            if (a[i][j]==3) S=num(i,j);
            if (a[i][j]==4) T=num(i,j);
        }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            if (a[i][j]==0||a[i][j]==3) bfs(i,j);
    spfa();if (dis[T]==inf) return puts("-1"),0;
    printf("%d\n%lld",dis[T],ans[T]);
    return 0;
}

Posted by jrws on Sat, 05 Jan 2019 22:45:09 -0800