題目:垃圾箱分佈
題意:選一垃圾桶的位置到所有居民點距離最佳,“到所有居民點的最短距離最長的地方”意思就是將每個垃圾桶位置的到居民點最短的路中篩選最長的那個的垃圾桶作爲結果~
思路:將所有垃圾桶的位置利用Dijkstra依次搜出到各個居名點的最短路,然後加入到一個結構體數組中,注意當超出限制範圍無需加入,最後按要求排序即可。
注意輸入時需要用字符串處理,將G的加上n,即垃圾桶的編號爲n以後的數,注意編號不只是個位數~
代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1020;
const int inf = 999999999;
int g[maxn][maxn],dis[maxn],visit[maxn];
int n,m,k,ds;
struct bag{
int id,mindis;
double avg;
}ans[15];
bool cmp(bag a,bag b){
if(a.mindis == b.mindis){
if(a.avg == b.avg) return a.id < b.id;
return a.avg < b.avg;
}
return a.mindis > b.mindis;//最短距離最長!
}
void init(){
for(int i=1;i<=n+m;i++)
for(int j=1;j<=n+m;j++)
if(i == j) g[i][j] = 0;else g[i][j] = inf;
}
void Dijkstra(int start){
for(int i=1;i<=n+m;i++){
dis[i] = g[start][i];
}
visit[start] = 1;
for(int i=1;i<=n+m;i++){
int minn = inf,record;
for(int j=1;j<=n+m;j++)
if(dis[j] < minn && !visit[j]){minn = dis[j];record = j;}
visit[record] = 1;
for(int j=1;j<=n+m;j++){
if(!visit[j] && dis[record] + g[record][j] < dis[j]){dis[j] = dis[record] + g[record][j];}
}
}
}
int trans(char a[],int start){
int sum = 0;
for(int i=start;a[i]!='\0';i++){sum*=10;sum += a[i] - '0';}
return sum;
}
int main()
{
char u[10],v[10];
int dist;
while(scanf("%d%d%d%d",&n,&m,&k,&ds)!=EOF){
init();
for(int i=0;i<k;i++){
scanf("%s%s%d",u,v,&dist);
int x,y;
if(u[0] == 'G') x = trans(u,1)+n;else x = trans(u,0);
if(v[0] == 'G') y = trans(v,1)+n;else y = trans(v,0);
g[x][y] = g[y][x] = dist;
}
int cnt = 0;
for(int i=n+1;i<=n+m;i++){
memset(visit,0,sizeof(visit));
Dijkstra(i);
int sum = 0,msd = inf;
int flag = 0;
for(int j=1;j<=n;j++) {
if(dis[j] > ds) {flag = 1;break;}//超出限制範圍
sum += dis[j];
msd = min(msd,dis[j]);//求垃圾桶到所有居民點最小距離
}
if(flag) continue;
ans[cnt].id = i-n;
ans[cnt].avg = (double)sum/n;
ans[cnt++].mindis = msd;
}
sort(ans,ans+cnt,cmp);
if(cnt > 0){
printf("G%d\n%.1lf %.1lf\n",ans[0].id,(double)ans[0].mindis,ans[0].avg);
}else printf("No Solution\n");
}
return 0;
}