【LGOJ1606】白银莲花池

为了让奶牛们娱乐和锻炼,农夫约翰建造了一个美丽的池塘。
这个长方形的池子被分成了M行N列个方格(1≤M,N≤30)
一些格子是坚固得令人惊讶的莲花,还有一一些格子是岩石,其余的只是美丽、纯净、湛蓝的水
贝西正在练习芭蕾舞,她站在一朵莲花上 ,想跳到另一朵莲花上去,她只能从一一朵莲花跳到另-朵莲花上
既不能跳到水里,也不能跳到岩石上,贝西的舞步很像象棋中的马步,最多时,西会有八个移动方向可供选择
约翰一直在观看贝西的芭蕾练习,发现她有时候不能跳到终点,因为中间缺了一些荷叶
于是他想要添加几朵莲花来帮助贝西完成任务
一贯节俭的约翰只想添加最少数星的莲花。当然,莲花不能放在石头上
请帮助约翰确定必须要添加的莲花的最少数量,以及有多少种放置这些莲花的方法

从起点,和水,向每一个可以放荷叶的位置建边
SPFA跑最短路的时候,顺便搞一下最短路计数
跑最短路的时候是点权,而要求的是边权
所以把答案减一即可

87分改了一个多小时,结果是dfs里面没有判vis...

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 1000005
#define inf 123456789123456789
using namespace std;

int n,m,u,v,xx1,yy1,xx2,yy2;
int a[35][35],id[35][35];

struct Edge
{
	int next,to;
}edge[N<<1];
int cnt=0,head[N];

inline void add_edge(int from,int to)
{
	edge[++cnt].next=head[from];
	edge[cnt].to=to;
	head[from]=cnt;
}

template<class T>inline void read(T &res)
{
	char c;T flag=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}


int dx[8]={2,1,-1,-2,2,1,-1,-2};
int dy[8]={1,2,2,1,-1,-2,-2,-1};
bool vis[35][35];
void dfs(int Id,int x,int y)
{
	if(vis[x][y]) return;
	vis[x][y]=true;
	for(register int i=0;i<8;++i)
	{
		int xx=x+dx[i];
		int yy=y+dy[i];
		if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]) continue;
		if(a[xx][yy]==1) dfs(Id,xx,yy);
		else if(a[xx][yy]!=2)
		{
			vis[xx][yy]=true;
			add_edge(Id,id[xx][yy]);
		}
	}
}

int S,T;
bool Vis[N];
ll dis[N],cont[N];
queue<int> q;
void spfa()
{
	for(register int i=1;i<=n*m;++i) dis[i]=inf;
	memset(cont,0,sizeof(cont));
	q.push(S);dis[S]=0;Vis[S]=1;cont[S]=1;
	while(!q.empty())
	{
		int u=q.front();q.pop();Vis[u]=0;
		for(register int i=head[u];i;i=edge[i].next)
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+1)
			{
				dis[v]=dis[u]+1;
				cont[v]=cont[u];
				if(!Vis[v])
				{
					q.push(v);
					Vis[v]=1;
				}
			}
			else if(dis[v]==dis[u]+1) cont[v]+=cont[u];
		}
	}
}

int main()
{
	read(n);read(m);
	for(register int i=1;i<=n;++i)
	{
		for(register int j=1;j<=m;++j)
		{
			read(a[i][j]);
			id[i][j]=(i-1)*m+j;
			if(a[i][j]==3) xx1=i,yy1=j;
			if(a[i][j]==4) xx2=i,yy2=j;
		}
	}
	for(register int i=1;i<=n;++i)
	{
		for(register int j=1;j<=m;++j)
		{
			if(a[i][j]==0||a[i][j]==3)
			{
				memset(vis,0,sizeof(vis));
				dfs(id[i][j],i,j);
			}
		}
	}
	S=id[xx1][yy1];
	T=id[xx2][yy2];
	spfa();
	if(dis[T]<inf) printf("%lld
%lld
",dis[T]-1,cont[T]);
	else puts("-1");
	return 0;
}
原文地址:https://www.cnblogs.com/tqr06/p/11657280.html