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
原创粉丝点击