Description

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

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

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

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

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

Input

第一行:两个用空格分开的整数:M和N

第二行到M+1行:第i+1行有N个用空格分开的整数,描述了池塘第i行的状态:

0为水,1为莲花,2为岩石,3为贝西所在的起点,4为贝西想去的终点。

Output

第一行:一个整数,需要增加的最少莲花数;如果无解,输出-1。

第二行:放置这些莲花的方案数量,保证这个数字不会超过一个64位的有符号整数,

如果第一行是-1,不要输出第二行。

这道题不错啊,表示很考思维.

首先,我们需要知道放多少莲花,如何放.

因此考虑最短路,方案数,我们就考虑最短路计数.(想信大家都会的)

这题的难点在于如何建边.

因为贝西可以跳任何一个位置,(任何一个有水的位置都可以放莲花)

所以我们不能单纯地从起点开始向其他点连边,所以我们要从每一个有水的地方开始.

由于岩石对答案没有贡献,所以不考虑连边.

多次\(dfs\)对整个图连边.

既然想到这了,你可能会发现,这是一个二维的最短路,记录状态不太好记录.

因此我们给每一个格子编号,像这样.

当然,还有其他编号方法,这样比较简单罢了.

算某一位置\((x,y)\)的编号的话,式子为\(idx[x][y]=(x-1)\times m+y\)

这样建边操作就简单多了.

然后后面只需要敲一个裸的最短路和最短路计数问题就好了.

输出添加的荷花的最小的数量的时候要\(-1\)

这是因为,这个数量实际上是点权,而我们跑最短路用的是边权.

一个点与两条边相连,所以要\(-1\)。

代码

  1. #include<cstdio>
  2. #include<cctype>
  3. #include<queue>
  4. #include<cstring>
  5. #define int long long
  6. #define clear(a,b) memset(a,b,sizeof a)
  7. #define R register
  8. using namespace std;
  9. inline void in(int &x)
  10. {
  11. int f=1;x=0;char s=getchar();
  12. while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
  13. while(isdigit(s)){x=x*10+s-'0';s=getchar();}
  14. x*=f;
  15. }
  16. int n,m,res[35][35],tot,idx[35][35],dis[1008611];
  17. int sx,sy,fx,fy,s,t,head[1008611],to[1008611];
  18. const int ax[]={2,1,-1,-2,2,1,-1,-2};
  19. const int ay[]={1,2,2,1,-1,-2,-2,-1};
  20. bool vis[35][35],inq[1008611];
  21. struct coc{int u,v;}edge[1008611];
  22. inline void add(int x,int y)
  23. {
  24. edge[++tot].u=head[x];
  25. edge[tot].v=y;
  26. head[x]=tot;
  27. }
  28. void dfs(int id,int x,int y)
  29. {
  30. if(vis[x][y])return;
  31. vis[x][y]=true;
  32. for(R int i=0;i<8;i++)
  33. {
  34. R int nx=x+ax[i],ny=y+ay[i];
  35. if(nx<1 || nx>n || ny>m || ny<1 || vis[nx][ny])continue;
  36. //刚开始写成return,尴尬死了 emm
  37. if(res[nx][ny]==1)dfs(id,nx,ny);
  38. else if(res[nx][ny]!=2)
  39. {
  40. vis[nx][ny]=true;
  41. add(id,idx[nx][ny]);
  42. }
  43. }
  44. }
  45. inline void spfa()
  46. {
  47. queue<int>q;
  48. for(R int i=1;i<=n*m;i++)dis[i]=2147483647;dis[s]=0;
  49. inq[s]=true;q.push(s);to[s]=1;
  50. while(!q.empty())
  51. {
  52. int u=q.front();q.pop();inq[u]=false;
  53. for(R int i=head[u];i;i=edge[i].u)
  54. {
  55. if(dis[edge[i].v]>dis[u]+1)
  56. {
  57. dis[edge[i].v]=dis[u]+1;
  58. to[edge[i].v]=to[u];
  59. if(!inq[edge[i].v])
  60. {
  61. q.push(edge[i].v);
  62. inq[edge[i].v]=true;
  63. }
  64. }
  65. else if(dis[edge[i].v]==dis[u]+1)
  66. to[edge[i].v]+=to[u];
  67. }
  68. }
  69. if(dis[t]<2147483647)printf("%lld\n%lld",dis[t]-1,to[t]);
  70. else printf("-1");
  71. }
  72. signed main()
  73. {
  74. in(n),in(m);
  75. for(R int i=1;i<=n;i++)
  76. for(R int j=1;j<=m;j++)
  77. {
  78. in(res[i][j]);
  79. idx[i][j]=(i-1)*m+j;
  80. if(res[i][j]==3)sx=i,sy=j;
  81. if(res[i][j]==4)fx=i,fy=j;
  82. }
  83. for(R int i=1;i<=n;i++)
  84. for(R int j=1;j<=m;j++)
  85. if(!res[i][j] or res[i][j]==3)
  86. clear(vis,0),dfs(idx[i][j],i,j);
  87. s=idx[sx][sy];t=idx[fx][fy];
  88. spfa();
  89. }

Dfs+Spfa【p1606】[USACO07FEB]荷叶塘Lilypad Pond的更多相关文章

  1. P1606 [USACO07FEB]荷叶塘Lilypad Pond(最短路计数)

    P1606 [USACO07FEB]荷叶塘Lilypad Pond 题目描述 FJ has installed a beautiful pond for his cows' aesthetic enj ...

  2. 洛谷 P1606 [USACO07FEB]荷叶塘Lilypad Pond 解题报告

    P1606 [USACO07FEB]荷叶塘Lilypad Pond 题目描述 FJ has installed a beautiful pond for his cows' aesthetic enj ...

  3. 洛谷 P1606 [USACO07FEB]荷叶塘Lilypad Pond【spfa】

    和bzoj同名题不一样! 起点和水点向花费一个荷花能到的第一个点连一条边权为1的有向边,然后跑计数spfa即可 #include<iostream> #include<cstdio& ...

  4. 【luogu P1606 [USACO07FEB]荷叶塘Lilypad Pond】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1606 这个题..第一问很好想,但是第二问,如果要跑最短路计数的话,零边权的花怎么办? 不如这样想,如果这个点 ...

  5. [洛谷P1606] [USACO07FEB] 荷叶塘Lilypad Pond

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

  6. 最短路【洛谷P1606】 [USACO07FEB]荷叶塘Lilypad Pond

    P1606 [USACO07FEB]荷叶塘Lilypad Pond 为了让奶牛们娱乐和锻炼,农夫约翰建造了一个美丽的池塘.这个长方形的池子被分成了M行N列个方格(1≤M,N≤30).一些格子是坚固得令 ...

  7. LuoguP1606 [USACO07FEB]荷叶塘Lilypad Pond 【最短路】By cellur925

    最短路好题!] 参考资料:学长 https://blog.csdn.net/TSOI_Vergil/article/details/52975779 学长太强了!!!%%% 题目传送门 ======= ...

  8. bzoj1698 / P1606 [USACO07FEB]白银莲花池Lilypad Pond

    P1606 [USACO07FEB]白银莲花池Lilypad Pond 转化为最短路求解 放置莲花的方法如果直接算会有重复情况. 于是我们可以先预处理和已有莲花之间直接互相可达的点,将它们连边(对,忽 ...

  9. BZOJ 1632: [Usaco2007 Feb]Lilypad Pond

    题目 1632: [Usaco2007 Feb]Lilypad Pond Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 390  Solved: 109[ ...

随机推荐

  1. js对象使用

    以下是js对象使用的两种方式 <script type="text/javascript"> var people = function () { } //方法1 pe ...

  2. 小红帽安装centos的yum的一些坑!

    [root@localhost ~]# lsanaconda-ks.cfg yum-3.4.3-158.el7.centos.noarch.rpm yum-updateonboot-1.1.31-45 ...

  3. 2、shader基本语法、变量类型、shader的三种形式、subshader、fallback、Pass LOD、tags

    新建一个shader,名为MyShader1内容如下: 1._MainTex 为变量名 2.“Base (RGB)”表示在unity编辑面板中显示的名字,可以定义为中文 3.2D 表示变量的类型 4. ...

  4. Singleton patterns 单件(创建型模式)

    1.模式分类 1.1  从目的来看: •      – 创建型(Creational)模式:负责对象创建. •      – 结构型(Structural)模式:处理类与对象间的组合. •      ...

  5. SpringBoot Rabbitmq接收消息

    官网地址:https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/#boot-features-amqp ...

  6. CSS3的笔记总结

    css3  就是css2 的一个升级版本.css2 是用来做效果渲染的,而css3 可以使做出来的效果更佳丰富. C3有兼容性问题,移动端支持稍微要好些.       坚持以下原则:         ...

  7. c# json 反序列化 泛型List 2行代码

    List<EncyTable> list = new List<EncyTable>(); var jsonReqeust = "[{ENCY_ID:775,ENCY ...

  8. GYM - 101147 K.Touristic Trip

    题意: 一个人从城市0开始旅行.一共有N座城市,他每到一座城市都会寄一张明信片.给出从一座城市到另一座城市的概率和在每座城市寄出每张明信片的概率.给出长度为k的寄明信片的序列.问在该序列的条件下在第Z ...

  9. NetAPP常用操作

    ===CIFS share======================================================================================= ...

  10. ES6--javascript判断一个字符串是否存在另一个字符串中

    es5中我们经常使用indexof()方法来判断一个字符串是否包含另外一个字符串中. 如果存在则返回匹配到的第一个索引值.如果没有则返回 -1.所以,判断一个字符串是否包含另外一个字符串中只需要判断是 ...