Pat 1018

本文探讨了一道看似简单的最短路径问题,实则涉及复杂的条件约束与资源管理的问题。通过对比Dijkstra算法与DFS回溯算法,指出在特定条件下Dijkstra算法的局限性,并给出基于DFS的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看起来是一道dijkstra题,实际上远没那么简单。dijkstra算法应该属于一种贪心算法,而要想应用贪心算法,就要确保之前的最优解是得到下一个最优解的基础,而这道题里面的条件约束中,路径长度是符合贪心算法的,但是自行车数量就不符合了!
例如
10 5 5 7
0 10 6 5 0
0 1 1
0 2 1
0 3 1
1 4 1
2 4 1
3 4 1
4 5 1
正确答案
0 0->2->4->5 0
若采用dijkstra将得出
4 0->3->4->5 0的错误答案
所以采用DFS回溯,要注意剪枝否则容易超时

#include<stdio.h>
#include<vector>
#define SIZE 505
#define INIFINTE 0x7fffffff
using namespace std;

struct graph{
    int dist;
    int takeback;
    int bringto;
    int size;
    int path[SIZE];
}cur,res;

int mat[SIZE][SIZE],car[SIZE],cnt;
bool visit[SIZE];

void DFS(int u,int n,int capacity,int aim){
    if (u == aim){
        if (cur.dist < res.dist)
            res = cur;
        else if (cur.dist == res.dist){
            if (cur.bringto < res.bringto)
                res = cur;
            else if (cur.bringto == res.bringto){
                if (cur.takeback < res.takeback)
                    res = cur;
            }
        }
        return;
    }
    for (int i = 1; i <= n;i++)
        if (!visit[i] && mat[u][i]){
            int tmpdist = cur.dist;
            int tmptakeback = cur.takeback;
            int tmpbringto = cur.bringto;
            cur.dist += mat[u][i];
            if (car[i] >= capacity || cur.takeback + car[i] >= capacity){
                cur.takeback += car[i] - capacity;
            }
            else {
                cur.bringto += capacity - cur.takeback - car[i];
                cur.takeback = 0;
            }
            visit[i] = true;
            cur.path[++cnt] = i;
            cur.size++;
            DFS(i, n, capacity, aim);
            visit[i] = false;
            cur.size--;
            cnt--;
            cur.dist = tmpdist;
            cur.bringto = tmpbringto;
            cur.takeback = tmptakeback;
        }
}

int main(){
    freopen("1.in", "r", stdin);
    int n, capacity, road, aim;
    scanf("%d%d%d%d", &capacity, &n, &aim, &road);
    int i;
    for (i = 1; i <= n; i++)
        scanf("%d", &car[i]);
    int from, to, dist;
    for (i = 0; i < road; i++){
        scanf("%d%d%d", &from, &to, &dist);
        mat[from][to] = mat[to][from] = dist;
    }
    res.bringto = INIFINTE;
    res.dist = INIFINTE;
    res.takeback = INIFINTE;
    cur.path[0] = 0;
    DFS(0,n,capacity/2,aim);
    printf("%d ", res.bringto);
    putchar('0');
    for (i = 1; i <= res.size; i++)
        printf("->%d", res.path[i]);
    printf(" %d\n", res.takeback);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值