1. 程式人生 > >$[ USACO 2007 FEB ] Lilypad Pond (Silver)$

$[ USACO 2007 FEB ] Lilypad Pond (Silver)$

!= har solution 計數 add reg bool ctype for


\(\\\)

\(Description\)


一張\(N\times M\)的網格,已知起點和終點,其中有一些地方是落腳點,有一些地方是空地,還有一些地方是壞點。

現在要從起點到終點,每次移動走日字\((\)橫一縱二或橫二縱一\()\),其中只能經過起點、終點、落腳點。

現在可以開發任意個數的空地變為落腳點,問找到合法路徑最少需要開發多少個空地,在滿足第一個條件下最少移動多少步,在滿足前兩個條件下有多少條不同的路徑。

  • \(N,M\in [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\n%lld\n%lld\n",dis[t],stp[t],ts[t]);
  else puts("-1");
  return 0;
}

$[\ USACO\ 2007\ FEB\ ]\ Lilypad\ Pond\ (Silver)$