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;
}