荷叶塘(建图+最短路)

为了让奶牛们娱乐和锻炼,农夫约翰建造了一个美丽的池塘。这个长方形的池子被分成了M行N列个方格(1≤M,N≤30)。一些格子是坚固得令人惊讶的莲花,还有一些格子是岩石,其余的只是美丽、纯净、湛蓝的水。

贝西正在练习芭蕾舞,她站在一朵莲花上,想跳到另一朵莲花上去,她只能从一朵莲花跳到另一朵莲花上,既不能跳到水里,也不能跳到岩石上。

贝西的舞步很像象棋中的马步:每次总是先横向移动一格,再纵向移动两格,或先纵向移动两格,再横向移动一格。最多时,贝西会有八个移动方向可供选择。

约翰一直在观看贝西的芭蕾练习,发现她有时候不能跳到终点,因为中间缺了一些荷叶。于是他想要添加几朵莲花来帮助贝西完成任务。一贯节俭的约翰只想添加最少数量的莲花。当然,莲花不能放在石头上。

请帮助约翰确定必须要添加的莲花的最少数量,以及有多少种放置这些莲花的方法。

Solution

我太傻了,

一开始就直接枚举周围点,有荷花连0遍,没有就连1边,再最短路计数一下。

首先,这个图就有问题,问的是摆放方案,我写的是路径方案。

而且这样会出现0环,spfa炸了。

所以我们采用dfs建图的方式,从一个点一直走知道碰到水,然后连一条1边就行了。

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define N 32
using namespace std;
queue<int>q;
int dis[N*N],n,m,a[N][N],id[N][N],tot,s,t,head[N*N],ji[N][N],num;
long long dp[N*N];
bool vis[N*N];
const int dx[8]={1,-1,-1,1,2,-2,2,-2};
const int dy[8]={2,2,-2,-2,1,1,-1,-1};
struct zzh{
    int n,to;
}e[200002];
inline void add(int u,int v){
    e[++tot].n=head[u];
    e[tot].to=v;
    head[u]=tot;
}
void dfs(int pos,int i,int j,int tag){
    ji[i][j]=num;
     if(!tag&&(a[i][j]==0||a[i][j]==4)){
         add(pos,id[i][j]);
         return;
     }
     for(int k=0;k<8;++k){
                int x=i+dx[k],y=j+dy[k];
                if(x<1||y<1||x>n||y>m||a[x][y]==2||ji[x][y]==num)continue;
              dfs(pos,x,y,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]!=4)num++,dfs(id[i][j],i,j,1);
    memset(dis,0x3f,sizeof(dis));
    q.push(s);dis[s]=0;dp[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();vis[u]=0;
        for(int i=head[u];i;i=e[i].n){
            int v=e[i].to;
            if(dis[v]>dis[u]+1){
                dis[v]=dis[u]+1;
                dp[v]=dp[u];
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                }
            }
            else if(dis[v]==dis[u]+1){
              dp[v]+=dp[u];
              if(!vis[v]){
                  vis[v]=1;
                  q.push(v);
              }
            }
        }
    }
    if(dis[t]==0x3f3f3f3f)cout<<-1;
    else cout<<dis[t]-1<<endl<<dp[t];
    return 0;
}

 

posted @ 2018-09-29 15:26  comld  阅读(210)  评论(0编辑  收藏  举报