zoukankan      html  css  js  c++  java
  • [ USACO 2007 FEB ] Lilypad Pond (Silver)

    (\)

    (Description)


    一张(N imes M)的网格,已知起点和终点,其中有一些地方是落脚点,有一些地方是空地,还有一些地方是坏点。

    现在要从起点到终点,每次移动走日字(()横一纵二或横二纵一()),其中只能经过起点、终点、落脚点。

    现在可以开发任意个数的空地变为落脚点,问找到合法路径最少需要开发多少个空地,在满足第一个条件下最少移动多少步,在满足前两个条件下有多少条不同的路径。

    • (N,Min [1,30])

    (\)

    (Solution)


    被上一个题干蒙直接(NC)......我还说Silver咋比Gold还难

    这题.......仔细读题之后错觉是(Gold)那题再加上一层限制的最短路,后来发现不是.......

    仔细读题,注意这次的方案数不再是放置落脚点的方案,而是路径数。

    那么我们就不必考虑选择不同原有落脚点导致方案同构的尴尬情况了,直接将每一个点向一步可以到达的点建边,如果是从空地向外建边代价为(1),其他为(0)即可。

    最短路计数时有双层限制,注意讨论更新的情况。

    (\)

    (Code)


    #include<cmath>
    #include<queue>
    #include<cctype>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 50
    #define M 60010
    #define R register
    #define gc getchar
    #define inf 9000000000000000ll
    using namespace std;
    typedef long long ll;
     
    inline int rd(){
       int x=0; bool f=0; char c=gc();
       while(!isdigit(c)){if(c=='-')f=1;c=gc();}
       while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
       return f?-x:x;
    }
     
    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};
     
    ll ts[N*N],stp[N*N],dis[N*N];
    int n,m,s,t,tot,cnt,num[N][N],mp[N][N],hd[N*N];
     
    struct edge{int w,to,nxt;}e[M<<1];
     
    inline void add(int u,int v,int w){
      e[++tot].to=v; e[tot].w=w;
      e[tot].nxt=hd[u]; hd[u]=tot;
    }
     
    inline void make(int ux,int uy){
      for(R int i=0,nx,ny;i<8;++i){
        nx=ux+dx[i]; ny=uy+dy[i];
        if(nx<1||nx>n||ny<1||ny>m) continue;
        add(num[ux][uy],num[nx][ny],mp[ux][uy]==0);
      }
    }
     
    queue<int> q;
     
    inline void SPFA(){
      memset(vis,0,sizeof(vis));
      memset(stp,0x3f,sizeof(stp));
      for(R int i=1;i<=cnt;++i) dis[i]=inf;
      q.push(s); dis[s]=0;
      ts[s]=1ll; stp[s]=0;
      while(!q.empty()){
        int u=q.front();
        q.pop(); vis[u]=0;
        for(R int i=hd[u],v;i;i=e[i].nxt)
          if(dis[v=e[i].to]>dis[u]+e[i].w){
            dis[v]=dis[u]+e[i].w;
            stp[v]=stp[u]+1; ts[v]=ts[u];
            if(!vis[v]) vis[v]=1,q.push(v);
          }
          else if(dis[v]==dis[u]+e[i].w&&stp[v]>stp[u]+1){
                stp[v]=stp[u]+1; ts[v]=ts[u];
                if(!vis[v]) vis[v]=1,q.push(v);
              }
          else if(dis[v]==dis[u]+e[i].w&&stp[v]==stp[u]+1) ts[v]+=ts[u];
      }
    }
     
    int main(){
      n=rd(); m=rd();
      for(R int i=1;i<=n;++i)
        for(R int j=1;j<=m;++j){
          mp[i][j]=rd();
          num[i][j]=++cnt;
          if(mp[i][j]==3) s=cnt;
          if(mp[i][j]==4) t=cnt;
        }
      for(R int i=1;i<=n;++i)
        for(R int j=1;j<=m;++j)
          if(mp[i][j]!=2) make(i,j);
      SPFA();
      if(dis[t]<inf) printf("%lld
    %lld
    %lld
    ",dis[t],stp[t],ts[t]);
      else puts("-1");
      return 0;
    }
    
  • 相关阅读:
    错排问题
    用GDAL/OGR去读shapefile
    聊聊MyBatis缓存机制
    一份平民化的应用性能优化检查列表(完整篇)--转
    微服务实战(七):从单体式架构迁移到微服务架构
    微服务实战(六):选择微服务部署策略
    微服务实战(五):微服务的事件驱动数据管理
    微服务实战(四):服务发现的可行方案以及实践案例
    微服务实战(三):深入微服务架构的进程间通信
    微服务实战(一):微服务架构的优势与不足
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9737730.html
Copyright © 2011-2022 走看看