PAT_A_1072
来源:互联网 发布:编程一小时官网 编辑:程序博客网 时间:2024/06/04 20:06
http://www.patest.cn/contests/pat-a-practise/1072
题目大意:
要建一个加油站 给定地图 其中一共有 M(M <=10)个候选点 N(N<=1000)个住宅 要求选出最佳的候选点 符合以下要求
1、所以住宅都应在加油站的服务范围 Ds 中
2、符合1要求下 保证离所有住宅都尽量远(安全考虑 我们判断时 只需判断离最近的住宅尽量远就行)
3、符合1、2 若有多个候选点 则选出距离之和最小的(题目描述是平均距离最小 相同意思)
4、经过1、2、3筛选还得不到最佳的 则选择候选点中下标最小的
//测试样例全过#include<stdio.h>#include<string.h>#define Inf 1<<30int n,m,k,d;int map[1100][1100],vst[1100],dis[1100];typedef struct{ int total; int imin; int mark;} Node;Node node[20];void Dijstra(int index){ int i,j,k,imax; dis[index]=0; //初始化 源点 index for(i=1; i<n+m; i++) { imax=Inf; for(j=1; j<=1000+m; j++) { if(!vst[j]&&dis[j]<imax) { imax=dis[j]; k=j; } if(j==n) j=1000; } //第一次 k 的值肯定是index 即第一个加到S集中的是源点 因为除dis[index]=0<imax 其余dis[i] 都初始为INF vst[k]=1; for(j=1; j<=1000+m; j++) { if(!vst[j]) { if(dis[k]+map[k][j]<dis[j]) { dis[j]=dis[k]+map[k][j]; } } if(j==n) j=1000; } }}int main(){ int i,j,dist; char from[10],to[10]; int fsum,tsum,tmp; while(scanf("%d %d %d %d",&n,&m,&k,&d) != EOF) { for(i=1; i<=1010; i++) { for(j=1; j<=1010; j++) { map[i][j]=Inf; } } for(i=0; i<k; i++) { scanf("%s %s %d",from,to,&dist); //处理地图 int lenf=strlen(from); tmp=1; if(from[0]=='G') { fsum=1000+from[lenf-1]-'0'; for(j=lenf-2; j>=1; j--) { tmp=tmp*10; fsum=fsum+(from[j]-'0')*tmp; } } else { fsum=from[lenf-1]-'0'; for(j=lenf-2; j>=0; j--) { tmp=tmp*10; fsum=fsum+(from[j]-'0')*tmp; } } int lent=strlen(to); tmp=1; if(to[0]=='G') { tsum=1000+to[lent-1]-'0'; for(j=lent-2; j>=1; j--) { tmp=tmp*10; tsum=tsum+(to[j]-'0')*tmp; } } else { tsum=to[lent-1]-'0'; for(j=lent-2; j>=0; j--) { tmp=tmp*10; tsum=tsum+(to[j]-'0')*tmp; } } //printf("%d %d\n",fsum,tsum); map[fsum][tsum]=map[tsum][fsum]=dist; //无向图 } int rtotal,rmin,flag; for(i=1001; i<=1000+m; i++) //1001-1010 代表 G1-G10 这些点分别调用Dijstra(i) 求出各自到所有住宅的最短路径 { for(j=1; j<=1010; j++) {//初始化 集合 S 最短路径 vst[j]=0; dis[j]=Inf; } Dijstra(i); //for(j=1;j<=n;j++) //printf("%d ",dis[j]); //printf("\n"); flag=0; rtotal=0; for(j=1; j<=n; j++) {//考察第Gi个候选点中 Gi 到每个住宅的最短距离是否在服务范围内 if(dis[j]<=d) {//如果在范围内 则累加 (用于后面的判优选取 选取距离和最小的候选点) rtotal=rtotal+dis[j]; } else { //如果有某一个点不住范围内 则该候选点不符合要求 标志flag = 1 flag=1; } } if(flag) {//GI不符合候选要求 其mark 值置为 0 node[i-1000].mark=0; } else { //若Gi到所有住宅的最短距离都在服务范围内 //则填写该点的属性 mark = 1 路径和 total = total node[i-1000].mark=1; node[i-1000].total=rtotal; rmin=Inf; for(j=1; j<=n; j++) { //选出该Gi到所有住宅最短距离最小的值 //用于后面的判优选取 因为Gi离所有住宅要尽量远 判断离最近住宅谁最远就行 if(dis[j]<rmin) rmin=dis[j]; } node[i-1000].imin=rmin; } } int rindex=-1,maxmin=-1,maxtotal=Inf; //最终选择 选出最优候选点 for(i=1; i<=m; i++) { if(node[i].mark) {//如果该点符合服务范围要求 if(node[i].imin>maxmin) {//离最近住宅距离 maxmin=node[i].imin;//距离综合 maxtotal=node[i].total;//标记该点 rindex=i; } else if(node[i].imin==maxmin) {//如果离最近住宅距离一样 if(node[i].total<maxtotal) {//选取距离和最小的 maxtotal=node[i].total; rindex=i; } }//应该还有一个判断 就是距离和也一样 选取Gi 中 i 最小的 估计测试数据没出这种极端的数据 } } if(rindex==-1) //如果连服务范围要求都找不到符合的 那肯定是没有解了//如果仅有一个候选点符合服务范围要求 那就它了 { printf("No Solution\n"); } else { printf("G%d\n",rindex); printf("%.1f %.1f\n",node[rindex].imin*1.0,node[rindex].total*1.0/n); } } return 0;}
0 0
- PAT_A_1072
- ASP.NET中使用UpdatePanel实现局部异步刷新方法和攻略
- orace 表以及相关知识1
- Pro/TOOLKIT示例程序:菜单,Checkbox和RadioButton菜单项
- 蒙奇奇便携无线蓝牙音箱电脑连接无声音解决办法
- C#绘制准心脚本
- PAT_A_1072
- 格式化输出数组
- 解析jQuery下的$.grep()方法和$.map()方法
- 第K大素数(水题)
- nyoj 123士兵杀敌(四)
- 对称字符串的最大长度 【微软面试100题 第七十三题】
- 第12章 基本认证机制
- 算法导论 31.1-13 将二进制整数转化为相应的十进制表示
- Pro/TOOLKIT示例程序:关系式