poj1724 roads(dfs)

问题描述:

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
s1e1L1T1
s1e2L2T2
...
sReRLRTR
s e是路起点和终点


解决办法:

数据结构|变量:

邻接表 (开始城市) 接着路(struct包含路的信息)(!注意:输入的数据会出现这样的错误,初始城市到达原城市)

数组 vistied[]深搜专用标记

minL[][] 优化(存储最短长度初始化为1<<30,下标分别是 到达城市、当前花费)

变量 minLen(就是答案)初始化为1<<30

totalLen当前长度

totalCost当前消费

过程:

DFS 传递参数是到达城市,终止条件就是判等N(符合找出所有能从1到N的路线),minLen选择totalLen中更小的数据和自己比较

深搜关键:for循环遍历邻接表,再dfs(到达城市节点)

优化条件:到达下一个城市(预估计)的

花费<K

长度<minLen||<minL[d][cost]

用continue终止(本次循环终止)

数据更新:以上变量及数组

dfs

弹回来了:把数据还原

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

int K, N, R;

struct Road
{
    int d, L, t;
};

vector<vector <Road> > cityMap(110);

int minLen;
int totalLen;
int totalCost;
int visited[110];
int minL[110][10100];

void DFS(int s)
{
    if(s == N)
    {
        minLen = min(minLen, totalLen);
        return;
    }
    for(int i = 0; i < (int)cityMap[s].size(); i++)
    {
        int d = cityMap[s][i].d;
        if(!visited[d])
        {
            int cost = totalCost + cityMap[s][i].t;
            if(cost > K)
                continue;
            if((totalLen + cityMap[s][i].L >= minLen) || totalLen + cityMap[s][i].L >= minL[d][cost])
                continue;
            totalCost += cityMap[s][i].t;
            totalLen += cityMap[s][i].L;
            minL[d][cost] = totalLen;//?
            visited[d] = 1;
            DFS(d);
            visited[d] = 0;
            totalLen -= cityMap[s][i].L;
            totalCost -= cityMap[s][i].t;
        }
    }
}

int main()
{
    scanf("%d%d%d", &K, &N, &R);
    for(int i = 0; i < R; i ++)
    {
        int s;
        Road r;
        scanf("%d%d%d%d", &s, &r.d, &r.L, &r.t);
        if(s != r.d)
        {
            cityMap[s].push_back(r);
        }
    }
    for(int i = 0; i < 110; i++)
        for(int j = 0; j < 10100; j++)
            minL[i][j] = 1 << 30;
    memset(visited, 0, sizeof(visited));
    totalCost = 0;
    totalLen = 0;
    visited[1] = 1;
    minLen = 1 << 30;
    DFS(1);

    if(minLen == 1 << 30)
        minLen = -1;

    printf("%d\n", minLen);

    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值