poj1724ROADS

http://poj.org/problem?id=1724

解题思路:
从城市 1开始深度优先遍历整个图,找到所有能到达 N 的走法 , 选一个最优的。
优化:
1) 如果当前已经找到的最优路径长度为L ,那么在继续搜索的过程中,总长度已经大
于L的走法,就可以直接放弃,不用走到底了
2) 用midL[k][m] 表示:走到城市k时总过路费为m的条件下,最优路径的长度。若在
后续的搜索中,再次走到k时,如果总路费恰好为m,且此时的路径长度已经超过
midL[k][m],则不必再走下去了。

#include <stdio.h>
#include <string.h>
#include <malloc.h>

#define city_Max 105
#define coin_Max 10005

typedef struct Road
{
    int D,L,T;//destination city,road length,toll
    struct Road* next;
}Road;

int S,K,N,R;//maximum number of coins,the total number of cities,the total number of roads.
int minL[city_Max][coin_Max];//minL[i][j]表示从1到i点的,花销为j的最短路的长度
int visited[city_Max],totalLen,totalCost,minLen=1<<30;
Road* cityMap[city_Max];

int min(int a,int b)
{
    return a<b?a:b;
}

void init()
{
    int i,j;
    Road *r;
    for(i=0;i<city_Max;i++)
        cityMap[i]=NULL;
    scanf("%d %d %d",&K,&N,&R);
    for(i=0;i<R;i++)
    {
        r=(Road*)malloc(sizeof(Road));
        scanf("%d %d %d %d",&S,&r->D,&r->L,&r->T);
        if(S!=r->D)
        {
            r->next=cityMap[S];
            cityMap[S]=r;
        }
    }
    memset(visited,0,sizeof(visited));
    for(i=0;i<city_Max;i++)
        for(j=0;j<coin_Max;j++)
            minL[i][j]=1<<30;
    totalLen=totalCost=0;
    visited[1]=1;
}

void Depth_FirstSearch(int s)//from s to N
{
    int i,d,cost,money;
    Road* p;
    if(s==N)
    {
        minLen=min(minLen,totalLen);
        return;
    }
    for(p=cityMap[s];p!=NULL;p=p->next)
    {
        d=p->D;
        if(!visited[d])
        {
            money=totalCost+p->T;
            if(money>K)//剪枝(money)
                continue;
            if(totalLen+p->L>=minLen||totalLen+p->L>=minL[d][money])//剪枝(pathLen)
                continue;
            totalLen+=p->L;
            totalCost+=p->T;
            minL[d][cost]=totalLen;
            visited[d]=1;
            Depth_FirstSearch(d);
            visited[d]=0;
            totalCost-=p->T;
            totalLen-=p->L;
        }
    }
}

int main()
{
    init();
    Depth_FirstSearch(1);
    if(minLen<(1<<30))
        printf("%d\n",minLen);
    else
        printf("-1\n");
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值