POJ1724ROADS(DFS+状态剪枝)

ROADS
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 14661 Accepted: 5314

Description

N cities named with numbers 1 ... N are connected with one-way roads. Each road has two parameters associated with it : the road length and the toll that needs to be paid for the road (expressed in the number of coins). 
Bob and Alice used to live in the city 1. After noticing that Alice was cheating in the card game they liked to play, Bob broke up with her and decided to move away - to the city N. He wants to get there as quickly as possible, but he is short on cash. 

We want to help Bob to find  the shortest path from the city 1 to the city N  that he can afford with the amount of money he has. 

Input

The first line of the input contains the integer K, 0 <= K <= 10000, maximum number of coins that Bob can spend on his way. 
The second line contains the integer N, 2 <= N <= 100, the total number of cities. 

The third line contains the integer R, 1 <= R <= 10000, the total number of roads. 

Each of the following R lines describes one road by specifying integers S, D, L and T separated by single blank characters : 
  • S is the source city, 1 <= S <= N 
  • D is the destination city, 1 <= D <= N 
  • L is the road length, 1 <= L <= 100 
  • T is the toll (expressed in the number of coins), 0 <= T <=100

Notice that different roads may have the same source and destination cities. 

Output

The first and the only line of the output should contain the total length of the shortest path from the city 1 to the city N whose total toll is less than or equal K coins. 
If such path does not exist, only number -1 should be written to the output. 

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

Sample Output

11

Source

思路:
用DFS搜索到达路径,然后判断费用是否满足条件,用了三个剪枝,剪枝1:当前len已经大于已找到的最短到达路径 剪枝2:当前费用已经大于了他有的钱 剪枝3:状态剪枝,如果到达了一个位置,之前也到达过,那么如果当前走过的距离已经大于之前的距离,那么就不用继续走下去了(因为已相同的金钱状态到达了本点,虽然之后点状态不一定(去向),就一定大于么?????这点有待证明)

//
//  main.cpp
//  ROADS
//
//  Created by 张嘉韬 on 2017/4/2.
//  Copyright © 2017年 张嘉韬. All rights reserved.
//

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
const int MAXM=10000+10;
const int MAXN=100+10;
const int MAXK=10000+10;
const int inf=1<<30;
struct road
{
    int v;
    int dist;
    int cost;
}roads[MAXM];
vector <road> map[MAXN];
int k,n,m,flag,minimum,vis[MAXN],minLen[MAXN][MAXK];
void DFS(int pos,int len,int fee)
{
    for(int i=0;i<map[pos].size();i++)
    {
        
        if(!vis[map[pos][i].v])
        {
            //cout<<map[pos][i].v<<endl;
            int templen=len+map[pos][i].dist;
            int tempfee=fee+map[pos][i].cost;
            if(templen>minLen[map[pos][i].v][tempfee]) continue;
            else minLen[map[pos][i].v][tempfee]=templen;
            if(templen>minimum||tempfee>k) continue;
            vis[map[pos][i].v]=1;
            if(map[pos][i].v==n)
            {
                minimum=min(minimum,templen);
                flag=1;
            }
            //cout<<map[pos][i].v<<endl;
            DFS(map[pos][i].v,templen,tempfee);
            vis[map[pos][i].v]=0;
        }
    }
}
int main(int argc, const char * argv[]) {
    //freopen("/Users/zhangjiatao/Desktop/input.txt","r",stdin);
    while(scanf("%d%d%d",&k,&n,&m)!=EOF)
    {
        memset(vis,0,sizeof(vis));
       // memset(minLen,inf,sizeof(minLen));
        for(int i=0;i<MAXN;i++)
            for(int j=0;j<MAXK;j++)
                minLen[i][j]=inf;
        flag=0;
        minimum=inf;
        for(int i=1;i<=m;i++)
        {
            road temp;
            int tempv;
            scanf("%d%d%d%d",&tempv,&temp.v,&temp.dist,&temp.cost);
            map[tempv].push_back(temp);
        }
        DFS(1,0,0);
        if(flag) printf("%d\n",minimum);
        else printf("-1\n");
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值