POJ 1062 昂贵的聘礼(枚举+dijkstra算法)

题目大意:

一个有向带权图,求源点到其他顶点的最短路径和该顶点值的和的最小值,典型的单元最短路径问题。不过每个顶点都有一个等级,源点到任意一个顶点最短路径上的任意两个顶点(包括源点和该顶点)的等级差不能超过给定的值。

解题思路:

我做这道题的经历:

1、题意理解错误,错认为只要满足相邻的结点的等级差在给定范围内就可以。

2、在dijkstra算法中记录每个结点的父亲结点,在讨论一个结点时,根据父亲结点不断往上遍历直到源点,如果该结点与往上遍历的所有父亲结点的等级差都在指定范围内,则更新该结点。(这用方法对有的路径不能考虑进去)

3、深搜,深搜算法写的不好,出现MLE

4、枚举一定范围内的点,dijkstra算法中只考虑在枚举范围内的顶点。(过题)

代码:

#include <cstdio>
#include <cstring>
#define M 125
const int INF = (1<<30)-1;

int m, n;
int p, l, x, t, v;
int value[M], charge[M][M];
int layer[M], low, high;
int vis[M], lowcost[M], path[M];

void dijkstra(int beg) {
    int i, j, minc;
    memset(vis, 0, sizeof(vis));
    vis[beg] = 1;
    for(i=0; i<n; i++) {        //在初始化lowcost[]数组的时候要判断其等级是否在指定范围,在这WA了多次
        if(layer[i]>=low && layer[i]<=high)
            lowcost[i] = charge[beg][i];
        else lowcost[i] = INF;
    }
    lowcost[beg] = 0;
    int pre = beg;
    for(int i=1; i<n; i++) {
        minc = INF;
        for(j=0; j<n; j++) {
            if(vis[j] == 0 && lowcost[pre]+charge[pre][j]<lowcost[j] &&
               layer[j] >=low && layer[j] <= high) {    //值考虑在枚举范围内的点
                lowcost[j] = lowcost[pre] + charge[pre][j];
            }
        }
        for(j=0; j<n; j++) {
            if(vis[j] == 0 && lowcost[j] < minc && layer[j]>=low && layer[j]<=high) {  //同样只需要考虑在
                minc = lowcost[j]; pre = j;                                            //枚举范围之内的点
            }
        }
        vis[pre] = 1;
    }
}

void init() {
    for(int i=0; i<n; i++) {
        for(int j=0; j<n; j++) {
            if(i == j) charge[i][j] = 0;
            else
                charge[i][j] = INF;
        }
    }
}

int main() {
    while(~scanf("%d%d", &m, &n)) {
        init();
        for(int i=0; i<n; i++) {
            scanf("%d%d%d", &p, &l, &x);
            value[i] = p; layer[i] = l;
            for(int j=0; j<x; j++) {
                scanf("%d%d", &t, &v);
                charge[i][t-1] = v;
            }
        }
        int ans = INF;
        for(low = layer[0]-m; low<=layer[0]; low++) {  //枚举等级范围,对于每个范围,用dijkstra算法
                high = low + m;                        //求出最优值。
                dijkstra(0);
                for(int i=0; i<n; i++) {
                    if(lowcost[i] + value[i] < ans) {
                        ans = lowcost[i] + value[i];
                    }
                }
        }
        printf("%d\n", ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值