【深搜题目】POJ:1724

题目链接:http://poj.org/problem?id=1724

题意:    N个城市,编号1到N。城市间有R条单向道路。 每条道路连接两个城市,有长度和过路费两个属性。 Bob只有K块钱,他想从城市1走到城市N。问最短共需要走多长的路。如果到不了N ,输出-1

    2<=N<=100 

    0<=K<=10000

     1<=R<=10000 每条路的长度 L, 1 <= L <= 100 每条路的过路费T , 0 <= T <= 100

输入:

K

N

R

s1 e1 L1 T1

s1 e2 L2 T2

...

sR eR LR TR

s e是路起点和终点

输出:最短路的长度。 

样例输入:

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

 样例输出:

11

解题思路

从城市 1开始深度优先遍历整个图,找到所有能到达 N 的走法,选一个最优的。

最优性剪枝:

1) 如果当前已经找到的最优路径长度为L ,那么在继续搜索的过程中,总长度已经大于等于L的走法,就可以直接放弃,不用走到底了

另一种通用的最优性剪枝思想 ---保存中间计算结果用于最优性剪枝:

2) 如果到达某个状态A时,发现前面曾经也到达过A,且前面那次到达A所花代价更少,则剪枝。这要求保存到达状态A的到目前为止的最少代价。

用midL[k][m] 表示:走到城市k时总过路费为m的条件下,最优路径的长度。若在后续的搜索中,再次走到k时,如果总路费恰好为m,且此时的路径长度已经超过midL[k][m],则不必再走下去了。

#include
#include
#include
#include
#include
#include
using namespace std;
struct Road
{
    int d,L,t;
};
int N,K,R;
vector < vector  > G(110);//用二维数组表示临界表,G[s]表示和s邻接的路
int minLen;//全局变量,记录最短的路径长度
int totalCost;//当前状态的花费
int totalLen;//当前状态的长度
int visited[110];
int minL[110][10010];//minL[i][j]的意义是当到达i点是花费为j时的最短路径
void Dfs(int s)
{
    if(s==N)
    {
        minLen=min(minLen,totalLen);
        return ;
    }
    int len=G[s].size();
    for(int i=0;iK)//如果当前花销大于K了
                continue;
            if(totalLen+r.L>=minLen)//如果当前的路径已经超过了已存在的最短路径,那就没必要往后dfs了
                continue;
            //如果存在两种方式都到达同一点并且花销相同,但是如果当前的长度大于另一种方式的长度,则continue
            if(totalLen+r.L>minL[r.d][totalCost+r.t])
                continue;
            minL[r.d][totalCost+r.t]=totalLen+r.L;
            visited[r.d]=1;
            totalCost+=r.t;
            totalLen+=r.L;
            Dfs(r.d);
            visited[r.d]=0;//因为可能存在多种方式的dfs的路径,所以每次dfs之后都要还原到之前的状态
            totalCost-=r.t;
            totalLen-=r.L;
        }

    }
}
int main()
{

    cin>>K>>N>>R;
    for(int i=0;i>s;
        cin>>r.d>>r.L>>r.t;
        G[s].push_back(r);
    }
    totalCost=0;
    totalLen=0;
    minLen=1<<30;//无穷大
    memset(visited,0,sizeof(visited));
    for(int i=1;i<=N;i++)
        for(int j=0;j<10010;j++)
            minL[i][j]=1<<30;
    visited[1]=1;
    Dfs(1);
    if(minLen<(1<<30))
        cout<

 

你可能感兴趣的:(深搜专题)