BZOJ1698: [Usaco2007 Feb]Lilypad Pond 荷叶池塘

一傻逼题调了两天。。

n<=30 * m<=30的地图,0表示可以放平台,1表示本来有平台,2表示不能走,3起点4终点,走路方式为象棋的日字,求:从起点走到终点,至少要放多少平台,以及放平台的方案数,无解-1。

方法一:其实能走直接平台的就可以直接走来走去,也就是算一个联通块。类似于tarjan,先把一大块缩成一点,然后连边走最短路。

错误!存在边权为0的边,会导致统计方案出现重复。比如:

圆圈走到三角形,直接走和绕一圈是一样的,但算了两次。

方法二:把0边去掉就行了。由于数据小,开个数组[a][b][c][d]表示a,b到c,d是否能通过填一块到达,这个数组只需对每个点做一次搜索就能出来。最后就是最短路啦。

不过边权为1,谁最短路会写迪杰呢?肯定bfs啦!

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<algorithm>
  5 //#include<iostream>
  6 using namespace std;
  7 
  8 int n,m;
  9 int a[33][33],can[33][33][33][33];
 10 #define maxn 1011
 11 #define maxm 10011
 12 struct Edge{int tx,ty,next;}edge[maxn*maxn];int first[33][33],le=2;
 13 #define LL long long
 14 void in(int sx,int sy,int tx,int ty)
 15 {
 16     Edge &e=edge[le];
 17     e.tx=tx;e.ty=ty;
 18     e.next=first[sx][sy];
 19     first[sx][sy]=le++;
 20 }
 21 int nx,ny;
 22 const int dx[]={1,1,2,2,-1,-1,-2,-2},dy[]={2,-2,1,-1,2,-2,1,-1};
 23 bool vis[33][33];
 24 void dfs(int x,int y)
 25 {
 26     vis[x][y]=1;
 27     for (int i=0;i<8;i++)
 28     {
 29         const int xx=x+dx[i],yy=y+dy[i];
 30         if (xx<1 || xx>n || yy<1 || yy>m || can[nx][ny][xx][yy]
 31         || a[xx][yy]==2 || vis[xx][yy]) continue;
 32         if (a[xx][yy]==0 || a[xx][yy]==4)
 33         {
 34             can[nx][ny][xx][yy]=1;
 35             continue;
 36         }
 37         dfs(xx,yy);
 38     }
 39 }
 40 const int inf=0x3f3f3f3f;
 41 int dis[33][33];LL way[33][33];
 42 struct qnode{int x,y;}q[maxn];int head,tail;
 43 void bfs(int sx,int sy)
 44 {
 45     head=0;tail=1;q[0].x=sx;q[0].y=sy;
 46     for (int i=1;i<=n;i++)
 47         for (int j=1;j<=m;j++)
 48             dis[i][j]=inf;
 49     dis[sx][sy]=0;way[sx][sy]=1;
 50     while (head!=tail)
 51     {
 52         const int nx=q[head].x,ny=q[head++].y;
 53         for (int i=first[nx][ny];i;i=edge[i].next)
 54         {
 55             const Edge &e=edge[i];
 56             if (dis[e.tx][e.ty]>dis[nx][ny]+1)
 57             {
 58                 dis[e.tx][e.ty]=dis[nx][ny]+1;
 59                 way[e.tx][e.ty]=way[nx][ny];
 60                 q[tail].x=e.tx,q[tail++].y=e.ty;
 61             }
 62             else if (dis[e.tx][e.ty]==dis[nx][ny]+1)
 63                 way[e.tx][e.ty]+=way[nx][ny];
 64         }
 65     }
 66 }
 67 int main()
 68 {
 69     scanf("%d%d",&n,&m);
 70     int sx,sy,tx,ty;
 71     for (int i=1;i<=n;i++)
 72         for (int j=1;j<=m;j++)
 73         {
 74             scanf("%d",&a[i][j]);
 75             if (a[i][j]==3) sx=i,sy=j;
 76             if (a[i][j]==4) tx=i,ty=j;
 77         }
 78     for (int i=1;i<=n;i++)
 79         for (int j=1;j<=m;j++)
 80         {
 81             memset(can[i][j],0,sizeof(can[i][j]));
 82             memset(vis,0,sizeof(vis));
 83             if (a[i][j]==2) continue;
 84             nx=i;ny=j;
 85             dfs(i,j);
 86         }
 87     memset(first,0,sizeof(first));
 88     for (int i=1;i<=n;i++)
 89         for (int j=1;j<=m;j++)
 90             for (int k=1;k<=n;k++)
 91                 for (int l=1;l<=m;l++)
 92                 {
 93                     if (can[i][j][k][l]) 
 94                     {
 95                         in(i,j,k,l);
 96                     }
 97                 }
 98     bfs(sx,sy);
 99     if (dis[tx][ty]==inf) puts("-1");
100     else printf("%d\n%lld\n",dis[tx][ty]-1,way[tx][ty]);
101     return 0;
102 }
View Code

 

posted @ 2017-09-21 12:22  Blue233333  阅读(167)  评论(0编辑  收藏  举报