hdu2962trucking

来源:互联网 发布:旅游导航软件 编辑:程序博客网 时间:2024/06/18 09:21

这道题难在要在一定条件下求得最短路。对车载高度进行二分,求出较高车载高度的情况下的最短路。通过判断是否能形成最短路来不断调整车载高度,如果在该车载高度情况下不能形成最短路则调低车载高度,否则调高车载高度。

#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>using namespace std;const int Max=1200;const int INF=1e9;int n,m,star,endd;int d[Max],Map[Max][Max],height[Max][Max];      //Map用来存放路长,height存放路限高bool vis[Max];                                  //vis标记该点是否已经访问过void init(){    for(int i=1; i<=n; i++)        for(int j=1; j<=n; j++)        {            Map[i][j]=INF;                      //将任意两点间路长初始化无穷            height[i][j]=0;                     //路限高初始化为0        }}bool dijstra(int lim){    memset(vis,0,sizeof(vis));                  //将所有点都初始化为未访问过    for(int j=1; j<=n; j++)    {        if(lim<=height[star][j])                //将与起点连通且该路限高大于车高的路更新        {            d[j]=Map[star][j];        }        else        {            d[j]=INF;                           //其余的路设为不通        }    }    vis[star]=1;                                //标记经过该点    for(int k=0; k<n; k++)                      //循环n次    {        int x=0,mm=INF;                         //将x设为不可能更新到的值,用来判断是否有与起点连通的路        for(int i=1; i<=n; i++)        {            //不可以是<=mm,如果有等号,则如果没有与源点的通路,就会一直更新到n,影响判断x,如果终点为n,则会一直逼近车载限高            if(!vis[i]&&d[i]<mm)               //找出未访问过的点到源点最小的节点x            {                mm=d[x=i];            }        }        if(x==0)                               //说明起止点间没通路,需调低车载高度            return false;        else if(x==endd)                       //说明找到最短路,需调高车载高度            return true;        vis[x]=1;        for(int i=1; i<=n; i++)        {            if(!vis[i]&&height[x][i]>=lim)     //如果x到未访问的点之间路的限高大于车载高度            {                d[i]=min(d[i],d[x]+Map[x][i]); //更新源点到未访问的点的路径长度            }        }    }}int main(){    int t=0;    while(scanf("%d%d",&n,&m)!=EOF&&(n+m)!=0)    {        init();        int aa,bb,cc,dd;        for(int i=1; i<=m; i++)        {            scanf("%d%d%d%d",&aa,&bb,&cc,&dd);            if(cc==-1)                cc=INF;            Map[aa][bb]=Map[bb][aa]=dd;             //双边处理            height[aa][bb]=height[bb][aa]=cc;        }        int limit,mid,left,right,ans;        scanf("%d%d%d",&star,&endd,&limit);         //起点终点和车载的限高        left=1,right=limit,ans=INF;        while(left<=right)                          //跳出循环时的right即为最优车载高度        {            mid=(left+right)/2;                     //对车载高度二分,求出能达到最高车载高度            if(dijstra(mid))                        //如果返回true,说明有起止点间的最短路            {                left=mid+1;                         //提高车载高度                ans=d[endd];                        //记录路径长度            }            else            {                right=mid-1;                        //降低车载高度            }        }        if(t)            printf("\n");        printf("Case %d:\n",++t);        if(ans==INF)                                //ans值最终没变说明起止点不通            printf("cannot reach destination\n");        else        {            printf("maximum height = %d\n",right);            printf("length of shortest route = %d\n",ans);        }    }    return 0;}

下面这个是用SPFA做的跟dijkstra的处理方法基本类似。

#include<stdio.h>#include<iostream>#include<queue>#include<string.h>#include<algorithm>using namespace std;const int MAX=999999999;const int edge_max=21000;       //边的最大值const int point_max=1110;        //点的最大值struct node{    int en;    int height;    int lenth;    int next;} edge[edge_max];int pos_in_edge[point_max];            //在边中的位置int dis[point_max],n,m,Star,End,limit;bool vis[point_max];queue<int>Q;void init(){    memset(pos_in_edge,-1,sizeof(pos_in_edge));     //初始化表头    int positn=1,sta,enb,lenc,heid;    for(int i=0; i<m; i++)    {        cin>>sta>>enb>>heid>>lenc;        if(heid==-1)            heid=MAX;        edge[positn].en=enb;        edge[positn].lenth=lenc;        edge[positn].height=heid;        edge[positn].next=pos_in_edge[sta];        pos_in_edge[sta]=positn++;        swap(sta,enb);                          //做双边处理        edge[positn].en=enb;        edge[positn].lenth=lenc;        edge[positn].height=heid;        edge[positn].next=pos_in_edge[sta];        pos_in_edge[sta]=positn++;    }    cin>>Star>>End>>limit;}void SPFA(int lim){    memset(vis,0,sizeof(vis));    fill(dis,dis+point_max,MAX);                //dis数组初始化为最大    dis[Star]=0;                                //处理源点    vis[Star]=true;    Q.push(Star);    while(!Q.empty())    {        int e_st_p=Q.front();                  //边的起点        vis[e_st_p]=false;        Q.pop();        for(int j=pos_in_edge[e_st_p]; j!=-1; j=edge[j].next)        {            if(edge[j].height<lim)                continue;            int e_en_p=edge[j].en;            //边的终点            if(dis[e_en_p]>edge[j].lenth+dis[e_st_p])   //松弛操作            {                dis[e_en_p]=edge[j].lenth+dis[e_st_p];                if(!vis[e_en_p])                {                    Q.push(e_en_p);                    vis[e_en_p]=true;                }            }        }    }}int main(){    int t=0;    while(scanf("%d%d",&n,&m)!=EOF&&(n+m)!=0)    {        init();        int left=1,right=limit,ans=MAX,mid;        while(left<=right)        {            mid=(left+right)/2;            SPFA(mid);            if(dis[End]!=MAX)            {                left=mid+1;                ans=dis[End];            }            else            {                right=mid-1;            }        }        if(t)            printf("\n");        printf("Case %d:\n",++t);        if(ans==MAX)            printf("cannot reach destination\n");        else        {            printf("maximum height = %d\n",right);            printf("length of shortest route = %d\n",ans);        }    }    return 0;}


0 0
原创粉丝点击