【ccf-csp题解】第2次csp认证-第四题-最优配餐-多源BFS

题目描述

思路讲解

这道题的数据量是10^6,直接用floyd算法,肯定是不行的

此处介绍新的思路:多源BFS

我们的核心目的是,对于每一个终点(即此处的顾客)能够找到离它最近的源点(即此处的餐馆)

思路如下,我们假想一个"超级源点"S,如图所示:

这个超级遇到源点距离每一个源点为0

那么算某个终点(比如A)到源点A,B,C,D的最短距离,就可以转换为求A到S的距离

代码应该怎么实现呢?

很简单,假设提前已经把S入队了,直接进入下一步:S出队,然后入队源点A,B,C,D即可

其它和普通BFS一毛一样

时间复杂度:O(N)

最后注意,答案可能爆int,所以用longlong

满分代码

cpp 复制代码
#include<iostream>
#include<queue>
#include<utility>
#include<cstring>
using namespace std;
const int N=1010;
typedef long long LL;
typedef pair<int,int>PII;
queue<PII>q;
int n,m,d,k;
int dist[N][N];
struct Target{
	int x,y,c;
}target[N*N];
LL res=0;
bool trap[N][N];
void bfs()
{
	int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
	while(q.size())
	{
		auto t=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
			int a=t.first+dx[i],b=t.second+dy[i];
			if(a<1||a>n||b<1||b>n||trap[a][b])continue;
			if(dist[a][b]>dist[t.first][t.second]+1)
			{
				dist[a][b]=dist[t.first][t.second]+1;
				q.push({a,b});
			}
		}
	}
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&k,&d);
	memset(dist,0x3f,sizeof dist);
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		q.push({x,y});
		dist[x][y]=0;
	}
	for(int i=1;i<=k;i++)
	{
		int x,y,c;
		scanf("%d%d%d",&x,&y,&c);
		target[i].x=x,target[i].y=y,target[i].c=c;
	}
	for(int i=1;i<=d;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		trap[x][y]=true;
	}
	bfs();
	for(int i=1;i<=k;i++)
	res+=(LL)dist[target[i].x][target[i].y]*target[i].c;
	cout<<res;
	return 0;
}
相关推荐
猷咪7 分钟前
C++基础
开发语言·c++
CSDN_RTKLIB14 分钟前
WideCharToMultiByte与T2A
c++
yyy(十一月限定版)29 分钟前
寒假集训4——二分排序
算法
星火开发设计29 分钟前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识
蒹葭玉树40 分钟前
【C++上岸】C++常见面试题目--操作系统篇(第二十八期)
linux·c++·面试
醉颜凉40 分钟前
【LeetCode】打家劫舍III
c语言·算法·leetcode·树 深度优先搜索·动态规划 二叉树
达文汐43 分钟前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗43 分钟前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
User_芊芊君子43 分钟前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
算法_小学生44 分钟前
LeetCode 热题 100(分享最简单易懂的Python代码!)
python·算法·leetcode