【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;
}
相关推荐
努力学习的小廉30 分钟前
深入了解linux系统—— 线程同步
linux·服务器·数据库·算法
数据爬坡ing32 分钟前
从挑西瓜到树回归:用生活智慧理解机器学习算法
数据结构·深度学习·算法·决策树·机器学习
luoganttcc33 分钟前
小鹏汽车 vla 算法最新进展和模型结构细节
人工智能·算法·汽车
骄傲的心别枯萎1 小时前
RV1126 NO.16:通过多线程同时获取H264和H265码流
linux·c++·音视频·rv1126
落羽的落羽1 小时前
【C++】特别的程序错误处理方式——异常机制
开发语言·c++
空山新雨(大队长)1 小时前
C 语言第一课:hello word c
c++·c·exe
春蕾夏荷_7282977251 小时前
c++ 第三方库与个人封装库
c++·三方库
牵牛老人2 小时前
Qt C++ 复杂界面处理:巧用覆盖层突破复杂界面处理难题之一
数据库·c++·qt
wallflower20202 小时前
滑动窗口算法在前端开发中的探索与应用
前端·算法
林木辛2 小时前
LeetCode热题 42.接雨水
算法·leetcode