7-14 垃圾箱分布 (30 分)

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

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

输入格式:
输入第一行给出4个正整数:N(≤10
3
)是居民点的个数;M(≤10)是垃圾箱候选地点的个数;K(≤10
4
)是居民点和垃圾箱候选地点之间的道路的条数;D
S

是居民点与垃圾箱之间不能超过的最大距离。所有的居民点从1到N编号,所有的垃圾箱候选地点从G1到GM编号。

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

P1 P2 Dist
其中P1和P2是道路两端点的编号,端点可以是居民点,也可以是垃圾箱候选点。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

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4;
ll dis[N];
int vist[N];
int n,m,k,d;

struct Node{
	ll dian;
	ll zhi; 
	friend bool operator<(const Node& a,const Node& b)
	{
		return a.zhi>b.zhi;
	}
};
vector<Node> v[N];

int getNum(string s)
{
	if(s[0]=='G'){
		return s[1]-'0'+n;
	}
	else{
		int ans=0;
		for(int i=0;i<s.size();i++){
			int t=s[i]-'0';
			ans=ans*10+t;
		}
			return ans;
	}

	
}
void dj(int x)
{
	priority_queue<Node> q;
	memset(dis,0x3f3f3f,sizeof(dis));
	memset(vist,0,sizeof(vist));
	q.push({x,0});  //入对 
	
	dis[x]=0;
	while(!q.empty()){
		Node H=q.top();
		q.pop();
		
		int cur=H.dian;
		if(vist[cur]) continue; //如果走过,这跳过 
		vist[cur]=1;//标记走过 
		
		for(int i=0;i<v[cur].size();i++){
		    Node next=v[cur][i];
		    if(!vist[next.dian]&&dis[next.dian]>dis[cur]+next.zhi){
		    	dis[next.dian]=dis[cur]+next.zhi;
		    	q.push({next.dian,dis[next.dian]});//放入新的点和直接到点的距离 
			}
		}
		
	}	
}


int main()
{
	int i,j,zhi;
	cin>>n>>m>>k>>d;
	string s1,s2;
	for(i=1;i<=k;i++){
		cin>>s1>>s2;
		int x=getNum(s1); //主要是处理垃圾同的,在居民点后+M 
		int y=getNum(s2);
		cin>>zhi;
		
		v[x].push_back({y,zhi});//双向边 
		v[y].push_back({x,zhi}); 
		
	}
	
    int id=0;
    double ans=INT_MAX,dis1=0;
    for(int i=n+1; i<=n+m; i++)  //枚举全部垃圾桶 
    {
        dj(i);
        ll maxx=0;
        ll minn=INT_MAX;
        int sum=0;
        for(int j=1; j<=n; j++)
        {
            minn=min(minn,dis[j]); //找出居民点到 垃圾桶的最短距离 
            sum+=dis[j];
            maxx=max(maxx,dis[j]);//最长 
        }
        
        if(maxx>d){  //不符合 
        	continue;
		}
		
		double avg=sum*1.0/n;//预先计算平均数 
		
		if(minn>dis1){ //要最短路径总和中的最小距离的最大 
			dis1=minn;
			id=i-n;
			ans=avg;  //注意这里要更新平均数 
			continue;
		}
		
		if(minn==dis1&&avg<ans){  //最小距离相等,要平均数最少的 
			dis1=minn;
			id=i-n;
			ans=avg;
		}
        
    }
 
    if(ans==INT_MAX)
        cout<<"No Solution"<<endl;
    else
    {
        cout<<"G";
        printf("%d\n%.1f %.1f",id,dis1,ans);
    }
	
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值