poj 1062 做题要细心。。。。。。dijkstra + 枚举

本文介绍了一个结合Dijkstra算法与枚举策略解决的最短路径问题。通过枚举不同等级范围来划分问题,针对每个子问题运行Dijkstra算法,最终找到最小成本的解决方案。

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

//===============================================//
//    poj:1062 昂贵的聘礼
//    dijkstra + 枚举 AC
//    最短路径问题
//==============================================//
#include <stdio.h>
#include <string.h>

const int NUM = 105;            //题目要求的的节点范围是100
const int MAX_INT = 0x3f3f3f;    //用于标识无法连接的点即一个无穷大值
int map[NUM][NUM], value[NUM], lev[NUM];    //图矩阵, 物品价值, 等级数组
int lim[NUM];    //用于每次枚举一个范围的等级标识数组,此题由等级将图划分为若干子图
int M, N;    //等级限制,物品个数

int Dijkstra();

int main()
{
    int i, j;
    int t;       
    int ans;    //最后结果
    int re;        //通过一次dijikstra计算后得到的一个结果
   
    while (scanf("%d %d", &M, &N) != EOF)
    {       
              memset(map, MAX_INT, sizeof(map));
           
            //所有物品到自己的权值为0
            for (i=0; i<=N; i++)
            {
                map[i][i] = 0;
            }
           
            //构图
            for (i=1; i<=N; i++)
            {
                scanf("%d %d %d", &value[i], &lev[i], &t);
               
                for (j=0; j<t; j++)
                {
                    int m, n;
                   
                    scanf("%d %d", &m, &n);
                    map[i][m] = n;
                }
            }
           
            ans = value[1];    //在没有任何交换时,结果为酋长要求的聘金
           
            //枚举等级范围,以酋长为等级中心则枚举 酋长等级-等级限制-->酋长等级+等级限制
            //这个范围内的所有区间这样做可以避免在一个等级内出现超出等级限制的情况
            //同时将问题分割为多个子问题一次进行dijikstra计算
            for (i=0; i<M+1; i++)
            {
                memset(lim, 0, sizeof(lim));
               
                for (j=1; j<=N; j++)
                {
                    if (lev[j] >= lev[1] - M + i && lev[j] <= lev[1] + i)
                    {
                        lim[j] = 1;   
                    }
                }
               
                //根据返回值选出最小的值
                re = Dijkstra();
                   
                if (ans > re)
                {
                    ans = re;
                }
               
            }
           
            printf("%d/n", ans);
    }
   
    return 0;
}

int Dijkstra()
{
    int visited[NUM] = {0};
    int dist[NUM];
    int i, j, k;
    int pos = 1;
    int res = MAX_INT;
   
    memset(dist, MAX_INT, sizeof(dist));
   
    for (i=1; i<=N; i++)
    {
        if (lim[i])
        {
            dist[i] = map[pos][i];
        }
    }
   
    for (i=1; i<=N; i++)
    {
        int min = MAX_INT;
       
        for (j=1; j<=N; j++)
        {
            if (!visited[j] && lim[j] && min > dist[j])
            {
                min = dist[j];
                pos = j;
            }
        }
       
        if (min == MAX_INT)
            break;

        visited[pos] = 1;
       
        for (k=1; k<=N; k++)
        {
            if (!visited[k] && lim[k] && dist[k] > dist[pos] + map[pos][k])
            {
                dist[k] = dist[pos] + map[pos][k];
            }
        }
    }
   
    for (i=1; i<=N; i++)
    {
        dist[i] += value[i];

        if (res > dist[i])
        {
            res = dist[i];
        }
    }
   
    return res;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值