转载请注明出处:優YoU http://blog.csdn.net/lyy289065406/article/details/6692382
大致题意:
给定一个图,图中每条路都有 路长Length 和 过路费Toll 两个参数,一条路连接两个城市,任意两个城市之间有且仅有一条路。
现在只有 K 块钱,要求从起点City1出发,到达终点CityN的最短路,也就是说在 K 花费内的最短路。
解题思路:
这个题其实有很多种解法的,只不过是题目描述用的模型是最短路的模型,其实方法多种多样,Discuss里有同学用dijkstra+A*,也有人用BFS+优先队列,也有人用直接用STL的priotrity_queue+剪枝.....。
我用了DFS+剪枝去做:
每个城市只能到达1次,每次找满足 Toll<RestMoney 的城市;当NowLen>MinLen就回溯,无需往下搜索了;递归出口是遍历所有允许的情况。
其实这题难度不大,关键是建立 邻接链表 去存储相同Source的路径去提高搜索效率。
因为Bob每进入一个Cityk,他就只能选择以k为源点的路径走向下一个城市,此时应该直接枚举所有以k为源点的路径。若使用了其他存储方式,则必然每次都要在所有路径中重新寻找以k为源点的路径,再枚举,这相当浪费时间。
Source修正:
CEOI 1998
谷歌搜索“CEOI '98”第一个就是了。。。。
http://www.hsin.hr/ceoi98/
//Memory Time //440K 250MS /*--- C++ Class ---*/ #include<iostream> using namespace std; class Road { public: int S,D,L,T; //Source,Destination,Length,Toll int next; //指向相同Source的下一条边 }; class info { public: info(int N,int R) { road=new Road[R+1]; vist=new bool[N+1]; ListTable_Head=new int[N+1]; memset(vist,false,sizeof(bool)*(N+1)); memset(ListTable_Head,-1,sizeof(int)*(N+1)); MinLen=1e7; pr=0; } ~info() { delete[] road; delete[] vist; delete[] ListTable_Head; } void input(int R); void output(void); void DFS(int NowCity,int NowLen,int RestMoney,int N); protected: Road* road; bool* vist; int* ListTable_Head; //邻接链表头指针数组 int MinLen; int pr; //road[]指针 }; void info::input(int R) { for(int i=1;i<=R;i++) { int s,d,l,t; cin>>s>>d>>l>>t; road[pr].S=s; road[pr].D=d; road[pr].L=l; road[pr].T=t; road[pr].next=ListTable_Head[s]; ListTable_Head[s]=pr++; } return; } void info::output() { cout<<(MinLen<1e7?MinLen:-1)<<endl; return; } void info::DFS(int NowCity,int NowLen,int RestMoney,int N) { if(NowLen>MinLen) return; if(NowCity==N && RestMoney>=0 && NowLen<MinLen) { MinLen=NowLen; return; } for(int i=ListTable_Head[NowCity];i!=-1;i=road[i].next) { int tD=road[i].D; int tL=road[i].L; int tT=road[i].T; if(!vist[tD] && RestMoney>=tT) { vist[tD]=true; DFS(tD,NowLen+tL,RestMoney-tT,N); vist[tD]=false; } } return; } int main(void) { int K,N,R; //Money,CityNum,RoadNum while(cin>>K>>N>>R) { info poj1724(N,R); poj1724.input(R); poj1724.DFS(1,0,K,N); poj1724.output(); } return 0; }
===============华丽的分割线================
//Memory Time //444K 235MS /*--- C++ Style ---*/ #include<iostream> using namespace std; const int inf=1e7; const int CitySize=101; const int RoadSize=10001; struct { int S,D,L,T; //Source,Destination,Length,Toll int next; //指向相同Source的下一条边 }road[RoadSize]; int pr; //road[]指针 int K,N,R; //Money,CityNum,RoadNum int MinLen; bool vist[CitySize]; int ListTable_Head[CitySize]; //邻接链表头指针数组 void DFS(int NowCity,int NowLen,int RestMoney) { if(NowLen>MinLen) return; if(NowCity==N && RestMoney>=0 && NowLen<MinLen) { MinLen=NowLen; return; } for(int i=ListTable_Head[NowCity];i!=-1;i=road[i].next) { int tD=road[i].D; int tL=road[i].L; int tT=road[i].T; if(!vist[tD] && RestMoney>=tT) { vist[tD]=true; DFS(tD,NowLen+tL,RestMoney-tT); vist[tD]=false; } } return; } int main(void) { while(cin>>K>>N>>R) { memset(ListTable_Head,-1,sizeof(ListTable_Head)); memset(vist,false,sizeof(vist)); pr=0; MinLen=inf; for(int i=1;i<=R;i++) { int s,d,l,t; cin>>s>>d>>l>>t; road[pr].S=s; road[pr].D=d; road[pr].L=l; road[pr].T=t; road[pr].next=ListTable_Head[s]; ListTable_Head[s]=pr++; } DFS(1,0,K); cout<<(MinLen<inf?MinLen:-1)<<endl; } return 0; }
Sample Input
5
6
7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2
19
6
7
1 2 2 2
1 3 2 2
1 4 2 2
2 5 5 10
4 5 7 7
3 5 10 5
5 6 5 10
15
12
16
1 8 20 0
1 2 10 0
2 8 5 0
1 7 100 0
2 3 5 1
3 4 5 1
4 5 5 1
5 6 5 1
6 12 5 1
8 12 10 20
8 9 1 1
9 10 1 1
10 11 1 1
11 7 2 10
7 12 10 1
11 4 1 0
Sample Output
11
14
30