洛谷 1606
来源:互联网 发布:简单电路 知乎 编辑:程序博客网 时间:2024/05/11 12:33
这道题与最短路有关应该是比较容易看出的,然后如果没有第二问,我们怎么建图都可以,比如说将莲花与莲花之间建一条边权为0的边,莲花与水建一条边权为1的边,水与水之间建一条边权为1的边,然后跑最短路。这样虽然能够解决第一问,但第二问却无从下手,我们可以感觉到第二问的方案数应该与最短路的方案数有关,但是如果按照上述建图的话,我们很难发现什么关系,因为如果经过的水面相同而经过的莲花不同,会被算作是不同的最短路,而实际上方案却是一样的,我们考虑不同的最短路指的是这条路径上经过的点不完全相同,那如果我们能在跑最短路时只经过水面,这样的最短路方案数一定是题目中要求的方案数,那我们怎么办呢,我们考虑其实莲花与莲花之间的边是没有意义的,它不过是为了保证连通性,同理,除起点和终点外的莲花与水之间的边也是没有意义的,那么我们考虑换一种建图方式,对于每个水,我们将从它能直接跳到或经过若干莲花后能跳到的水连边,将起点和终点与水连边,这样跑最短路,我们发现经过这样建图后最短路上的点除起点和终点是莲花之外,其余的点全是水,这样不同的最短路就对应着经过了不同的水,也就对应着不同的放莲花的方案。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define maxn 130005int n,m,g[35][35],sx,tx,sy,ty,l,cnt;int pre[maxn],last[maxn],other[maxn];int quex[1000000],quey[1000000],que[1000000];const int dx[9]={0,1,1,2,2,-1,-1,-2,-2};const int dy[9]={0,-2,2,-1,1,-2,2,-1,1};int flag[35][35],dis[1005];bool vis[1005][1005],vist[maxn];long long f[1005];void connect(int x,int y){ l++; pre[l]=last[x]; last[x]=l; other[l]=y; }void bfs(int fx,int fy){ flag[fx][fy]=++cnt; int h=1,t=0; for (int i=1;i<=8;i++) { int xx=fx+dx[i]; int yy=fy+dy[i]; if (xx<1||xx>n||yy<1||yy>m) continue; if (flag[xx][yy]==cnt) continue; flag[xx][yy]=cnt; if (g[xx][yy]!=2&&g[xx][yy]!=0) { t++; quex[t]=xx;quey[t]=yy; int id1=(fx-1)*m+fy; int id2=(xx-1)*m+yy; if (vis[id1][id2]) continue; connect(id1,id2); connect(id2,id1); vis[id1][id2]=vis[id2][id1]=1; } else if (g[xx][yy]==0) { int id1=(fx-1)*m+fy; int id2=(xx-1)*m+yy; if (vis[id1][id2]) continue; connect(id1,id2); connect(id2,id1); vis[id1][id2]=vis[id2][id1]=1; } } while (h<=t) { int x=quex[h],y=quey[h];h++; for (int i=1;i<=8;i++) { int xx=x+dx[i]; int yy=y+dy[i]; if (xx<1||xx>n||yy<1||yy>m) continue; if (flag[xx][yy]==cnt) continue; flag[xx][yy]=cnt; if (g[xx][yy]==0) { int id1=(fx-1)*m+fy; int id2=(xx-1)*m+yy; if (vis[id1][id2]) continue; connect(id1,id2); connect(id2,id1); vis[id1][id2]=vis[id2][id1]=1; } else if (g[xx][yy]!=2&&g[xx][yy]!=0) { t++; quex[t]=xx;quey[t]=yy; } } }}void spfa(void){ memset(dis,53,sizeof dis); dis[(sx-1)*m+sy]=0; que[1]=(sx-1)*m+sy; int h=1,t=1; while (h<=t) { int u=que[h];h++; vist[u]=0; for (int p=last[u];p;p=pre[p]) { int v=other[p]; if (dis[v]>dis[u]+1) { dis[v]=dis[u]+1; if (!vist[v]) { que[++t]=v; vist[v]=1; } } } }}void solve(void){ memset(vist,0,sizeof vist); que[1]=(sx-1)*m+sy;f[que[1]]=1; int h=1,t=1; while (h<=t) { int u=que[h];h++; for (int p=last[u];p;p=pre[p]) { int v=other[p]; if (dis[v]==dis[u]+1) { f[v]+=f[u]; if (!vist[v]) { que[++t]=v; vist[v]=1; } } } }}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { scanf("%d",&g[i][j]); if (g[i][j]==3) {sx=i;sy=j;} if (g[i][j]==4) {tx=i;ty=j;} } bfs(sx,sy); bfs(tx,ty); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (g[i][j]==0) bfs(i,j); spfa(); if (dis[(tx-1)*m+ty]>1e7) { printf("-1\n"); return 0; } printf("%d\n",dis[(tx-1)*m+ty]-1); solve(); printf("%lld\n",f[(tx-1)*m+ty]); return 0; }
0 0
- 洛谷 1606
- 1606
- POJ 1606
- poj 1606 Jugs
- poj 1606 Jugs (BFS)
- POJ 1606 Jugs
- poj 1606 Jugs
- POJ 1606 Jugs
- 1606 - Amphiphilic Carbon Molecules
- poj 1606 bfs方法
- poj 1606 Jugs
- POJ-1606 Jugs
- HUST 1606 Naive
- HUST 1606 - Naive
- Problem 1606 - Funny Sheep
- ssl 1606 选课
- UVA(1606)
- ZCMU—1606
- C#-播放器相关
- Python 学习笔记(5) -数据类型 1
- 二叉树的基本操作 (二叉链表实现)
- C#-DES加解密
- 【HDOJ】5945 Fxx and game
- 洛谷 1606
- MyBatis快速入门
- C#-WiFi共享
- 2016.10.30小鹿ins翻译
- 1027. Colors in Mars (20)
- jQuery笔记——动画设计——动画设计基础
- C#-获取磁盘,cpu,内存信息
- Boost库的使用(Windows)
- Mysql必知必会(笔记)【管理事务处理】