这是一个典型的深搜问题,当常常会超时,关键在于如何剪枝,直接分析dfs代码吧!!!
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int K,N,R;
struct Road
{
int d,L,t;
};
vector< vector<Road> > G(110);
int minLen;//最小长度
int totalCost;//总花费
int totalLen;//当前总长度
int visited[110]; //判断是否走过该点
int midL[110][10010];//midl[i][j],代表起点i时花费为j时的最小长度;
void Dfs(int s)
{
if( s == N)//如果s是终点
{
minLen = min(minLen, totalLen);
return;
}
for(int i = 0; i < G[s].size(); ++i)//循环s连接的的路
{
Road r = G[s][i];
if(totalCost + r.t > K) continue;//花费已经超过了总花费则无需再找下去
if(totalLen + r.L >= minLen) continue;//长度以及超过最小长度也无需找下去
if( !visited[r.d])
{
if(midL[r.d][totalCost + r.t] <= totalLen + r.L)continue;//如果起点和花费都相同时,此时的花费比之前花费还多,则也无需再找下去。
midL[r.d][totalCost + r.t] = totalLen + r.L;//一定要先continue再进行赋值语句!!!!!否走提前跳出循环,值已经改变了。
totalCost += r.t;
totalLen += r.L;
visited[r.d] = 1;
Dfs(r.d);
totalCost -= r.t;//r,d找完之后要减去r,d的值。
totalLen -= r.L;
visited[r.d] = 0;
}
}
}
int main()
{
cin>>K>>N>>R;
for(int i = 0; i < R; ++i)
{
int s;
Road r;
cin>>s>>r.d>>r.L>>r.t;
if( s != r.d) G[s].push_back(r);
}
memset(visited, 0, sizeof(visited));
for(int i = 0; i < 110; ++i)
{
for(int j = 0; j < 10010; ++j)
{
midL[i][j] = 1 << 30;
}
}
totalCost = 0;
totalLen = 0;
minLen = 1 << 30;
visited[1] = 1;
Dfs(1);
if(minLen < (1 << 30)) cout<<minLen<<endl;
else cout<<-1<<endl;;
}