天梯赛倒计时3天

210 阅读3分钟

L3-005 垃圾箱分布

分数 30

全屏浏览题目

切换布局

作者 陈越

单位 浙江大学

大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。

现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。

输入格式:

输入第一行给出4个正整数:N(≤103)是居民点的个数;M(≤10)是垃圾箱候选地点的个数;K(≤104)是居民点和垃圾箱候选地点之间的道路的条数;DS​是居民点与垃圾箱之间不能超过的最大距离。所有的居民点从1到N编号,所有的垃圾箱候选地点从G1到GM编号。

随后K行,每行按下列格式描述一条道路:

P1 P2 Dist

其中P1P2是道路两端点的编号,端点可以是居民点,也可以是垃圾箱候选点。Dist是道路的长度,是一个正整数。

输出格式:

首先在第一行输出最佳候选地点的编号。然后在第二行输出该地点到所有居民点的最小距离和平均距离。数字间以空格分隔,保留小数点后1位。如果解不存在,则输出No Solution

输入样例1:

4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2

输出样例1:

G1
2.0 3.3

输入样例2:

2 1 2 10
1 G1 9
2 G1 20

输出样例2:

No Solution

今天来点ex图论,dijkstra(),源于我两天都因为读入寄了,t m d,ysu的llh佬交了我stoi()是将字符串转化为数字,to_string()可以将数字转化成字符串,然后s.find("")!=string::npos就是说明可以找到这个字符。剩下的就简单了,就是最短路筛选。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=20010;
const int M=1015;
#define x first
#define y second
int n,m,k,ds;
int idx=0,e[N],ne[N],h[N],w[N],dist[M],minn[N];
double avg[N];
void add(int a,int b,int c){
	e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
bool st[M];
typedef pair<int,int> PII;
unordered_map<string,int> mp;
vector<int> ans;
void dijkstra(int root){
	double ans=0;
	memset(st,false,sizeof st);
	memset(dist,0x3f,sizeof dist);
	priority_queue<PII,vector<PII>,greater<PII>> heap;
	heap.push({0,root});
	dist[root]=0;
	while(heap.size()){
		PII t=heap.top();
		heap.pop();
		int ver=t.y,distance=t.x;
		if(st[ver]) continue;
		st[ver]=true;
		for(int i=h[ver];~i;i=ne[i]){
			int j=e[i];
			if(dist[j]>distance+w[i]){
				dist[j]=distance+w[i];
				heap.push({dist[j],j});
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(dist[i]<=ds){
			minn[root]=min(minn[root],dist[i]);
			ans+=dist[i];			
		}
		else minn[root]=-1;	
	}
	avg[root]=double(ans)/n;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0); 
	cin>>n>>m>>k>>ds;
	memset(h,-1,sizeof h);
	for(int i=1;i<=m;i++) mp["G"+to_string(i)]=n+i;
	int cnt=n+m;
	while(k--){
		string be,en;
		int d;
		cin>>be>>en>>d;
		int a,b;
		if(be.find("G")!=string::npos) a=mp[be];
		else a=stoi(be);
		if(en.find("G")!=string::npos) b=mp[en];
		else b=stoi(en);
		add(a,b,d);
		add(b,a,d);
	}
	memset(minn,0x3f,sizeof minn);
	for(int i=n+1;i<=cnt;i++){
		dijkstra(i);
	}
	int mm=0;
	for(int i=n+1;i<=cnt;i++) mm=max(minn[i],mm);
	if(mm==0) cout<<"No Solution";
	
	else{
		for(int i=n+1;i<=cnt;i++) if(minn[i]==mm) ans.push_back(i);
		sort(ans.begin(),ans.end());
		double av=1e9;
		for(int i=0;i<ans.size();i++) av=min(av,avg[ans[i]]);
		for(int i=0;i<ans.size();i++){
			if(avg[ans[i]]==av){
				cout<<'G'<<ans[i]-n<<endl;
				printf("%.1lf %.1lf",double(minn[ans[i]]),avg[ans[i]]);
				break;
			}
		}
	}
	return 0;
}

天梯赛不留遗憾,加油!