ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 洛谷P1606 [USACO07FEB]Lilypad Pond G

2021-12-25 09:36:16  阅读:150  来源: 互联网

标签:洛谷 val int 题解 void mp way USACO07FEB dis


一道建图 毒瘤 好题。 传送门

题目上不是很像建图,但是想到建图并不是很难。

这一手把通往荷花的路权值记为 \(0\) ,把通往水的边权值记为 \(1\) 。 直接上 dijkstra , 20min 写完 die 码。

#include <bits/stdc++.h>
#define debug puts("I ak IOI several times");
#define pb push_back
using namespace std;
template <typename T>inline void read(T& t){
    t=0; register char ch=getchar(); register int fflag=1;
    while(!('0'<=ch&&ch<='9')){if(ch=='-') fflag=-1;ch=getchar();}
    while(('0'<=ch&&ch<='9')){t=((t<<1)+(t<<3))+ch-'0'; ch=getchar();} t*=fflag;
}
template <typename T,typename... Args> inline void read(T& t, Args&... args){
    read(t);read(args...);
}
template <typename T>inline void write(T x){
    if(x<0) putchar('-'),x=~(x-1); int s[40],top=0;
    while(x) s[++top]=x%10,x/=10; if(!top) s[++top]=0;
    while(top) putchar(s[top--]+'0');
}
const int MAXN=45*45,MAXM=10000000,inf=0x3f3f3f3f;
struct Edge{
	int to,val,nxt;
}e[MAXM];
struct Node{
	int to,val;
	bool operator < (const Node &node) const{
		return val>node.val;
	}
};
priority_queue<Node>Q;
bool vis[MAXN];
int head[MAXN],cnt,n,m,_mp[50][50],sta,en,dis[MAXN],way[MAXN];
const int dx[]={1,1,-1,-1,2,2,-2,-2},
		  dy[]={2,-2,2,-2,1,-1,1,-1};
inline int Num(int x,int y){return (x-1)*m+y;}
void add(int x,int y,int val){
	e[++cnt]={y,val,head[x]};
	head[x]=cnt;
	return;
}
void ADD(int x,int y){
	if(_mp[x][y]==3) sta=Num(x,y);
	if(_mp[x][y]==4) en=Num(x,y);
	for(int i=0;i<8;++i){
		int nx=x+dx[i],ny=y+dy[i];
		if(nx<1||ny<1||nx>n||ny>m) continue;
		if(_mp[nx][ny]!=2){
			if(_mp[nx][ny]==1||_mp[nx][ny]==4) add(Num(x,y),Num(nx,ny),0);
			if(_mp[nx][ny]==0) add(Num(x,y),Num(nx,ny),1);
		}
	}
}
void intt(){
	read(n,m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			read(_mp[i][j]);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			ADD(i,j);
}
void dijk(){
	intt();
	memset(dis,0x3f,sizeof(dis));
	memset(way,0,sizeof(way));
	dis[sta]=0; Q.push({sta,0});
	way[sta]=1;
	while(!Q.empty()){
		int u=Q.top().to; Q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(dis[v]>dis[u]+e[i].val&&!vis[v]){
				dis[v]=dis[u]+e[i].val;
				way[v]=way[u];
				Q.push({v,dis[v]});
			}else if(dis[v]==dis[u]+e[i].val) way[v]+=way[u];
		}
	}
	if(!way[en]) cout<<-1<<endl;
	else cout<<dis[en]<<endl<<way[en]<<endl;
	return;
}
int main(){
	dijk();
    return 0;
}
//Welcome back,Chtholly.

50pts ,查看一手错误信息,第二行的问题。

什么问题呢,反手查看题解,发现。题目并不是问的最短路的条数,而是问有多少种放置荷花的方式。

那么怎么办呢,就用 dfs 建边,只对于水、起点建边,然后如果是荷花,那么把它看成上一个水,建边建在水上,而不是荷花上。

再加上亿点点细节。

#include <bits/stdc++.h>
#define debug puts("I ak IOI several times");
#define pb push_back
using namespace std;
template <typename T>inline void read(T& t){
    t=0; register char ch=getchar(); register int fflag=1;
    while(!('0'<=ch&&ch<='9')){if(ch=='-') fflag=-1;ch=getchar();}
    while(('0'<=ch&&ch<='9')){t=((t<<1)+(t<<3))+ch-'0'; ch=getchar();} t*=fflag;
}
template <typename T,typename... Args> inline void read(T& t, Args&... args){
    read(t);read(args...);
}
template <typename T>inline void write(T x){
    if(x<0) putchar('-'),x=~(x-1); int s[40],top=0;
    while(x) s[++top]=x%10,x/=10; if(!top) s[++top]=0;
    while(top) putchar(s[top--]+'0');
}
const int MAXN=51*51,MAXM=10000000,inf=0x3f3f3f3f;
struct Edge{
	int to,val,nxt;
}e[MAXM];
struct Node{
	int to,val;
	bool operator < (const Node &node) const{
		return val>node.val;
	}
};
priority_queue<Node>Q;
bool vis[MAXN],visi[MAXN][MAXN];
int head[MAXN],cnt,n,m,_mp[50][50],sta,en,dis[MAXN];
long long way[MAXN];
const int dx[]={1,1,-1,-1,2,2,-2,-2},
		  dy[]={2,-2,2,-2,1,-1,1,-1};
inline int Num(int x,int y){return (x-1)*m+y;}
void add(int x,int y,int val){;
	e[++cnt]={y,val,head[x]};
	head[x]=cnt;
	return;
}
void dfs(int x,int y,int num){
	visi[x][y]=1;
	for(int i=0;i<8;++i){
		int nx=dx[i]+x,ny=dy[i]+y;
		if(visi[nx][ny]||_mp[nx][ny]==2||nx<1||ny<1||nx>n||ny>m) continue;
		if(_mp[nx][ny]==1) dfs(nx,ny,num);
		else visi[nx][ny]=1,add(num,Num(nx,ny),1);
	}
}
void ADD(int x,int y){
	if(_mp[x][y]==3) sta=Num(x,y);
	if(_mp[x][y]==4) en=Num(x,y);
	if(_mp[x][y]==0||_mp[x][y]==3||_mp[x][y]==4){
		memset(visi,0,sizeof(visi));
		dfs(x,y,Num(x,y));
	}
	return;
}
void intt(){
	read(n,m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			read(_mp[i][j]);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			ADD(i,j);
}
void dijk(){
	intt();
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	memset(way,0,sizeof(way));
	dis[sta]=0; Q.push({sta,0});
	way[sta]=1;
	while(!Q.empty()){
		int u=Q.top().to; Q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(dis[v]>dis[u]+e[i].val){
				dis[v]=dis[u]+e[i].val;
				way[v]=way[u];
				Q.push({v,dis[v]});
			}else if(dis[v]==dis[u]+e[i].val) way[v]+=way[u];
		}
	}
	if(!way[en]) cout<<-1<<endl;
	else cout<<dis[en]-1<<endl<<way[en]<<endl;
	return;
}
signed main(){
	dijk();
    return 0;
}
//Welcome back,Chtholly.

标签:洛谷,val,int,题解,void,mp,way,USACO07FEB,dis
来源: https://www.cnblogs.com/Mercury-City/p/15729827.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有