POJ-1062 昂贵的聘礼 解题报告

Dijstra算法

题目链接: POJ-1062 昂贵的聘礼

解题思路

通过题意,我们可以很明显的看出来,物品的交换流程可以构成一个有向图,而且这个图是有边权的。

构建这个图的过程如下:
因为每个物品都有相应的替代物品,所以我们可以在替代物品和该物品之间建立一条边,从替代物品指向该物品,并且边上的权值为优惠价格。这样建完所有的边之后,我们可以创造一个起点,这个起点对所有的物品都有一个出边,并且边上的权值为该物品的原价。最终我们的结果肯定是一个从起点到编号为1的物品的最短路。

通过上面的分析,现在我们的问题是如何将每个物品主人的等级考虑进去,根据题意我们了解到,我们最终的结果是在那条最短路上,最高的等级与最低的等级之间的差不能超过M,这里是特别容易弄错的地方,我之前以为是如果A与B之间的等级差小于M,B与C之间的等级差小于M就能一直从A交换到C……

解题关键:最终的我们得到的最短路,里面肯定是有一个点X的等级是最低的,那么我们可以在原图上找到所有的比这个X点等级高的,而且那些点与X点之间的等级差必须小于等于M,最终的路径肯定是这些点里面产生的。所以我们枚举每一个可能的点,将这个被枚举的点当作X点,然后找到所有满足上述条件的其他点,在这些点之间跑单源最短路。每次枚举X点我都能得到一个最短路径值,最终我们取最小的路径值便是结果。

解题代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 110;
const int INF = 0X3fffffff;

int M,N;
int dis[MAXN][MAXN];
int cost[MAXN];
bool vis[MAXN];
struct Node {
    int price;
    int level;
    int itemCount;
    int itemNum[MAXN];
    int itemPrice[MAXN];
}node[MAXN];

void initDis() {
    for(int i = 0; i <= N; i++) {
        dis[i][i] = 0;
        for(int j = i+1; j <= N; j++) {
            dis[i][j] = dis[j][i] = INF;
        }
    }
}
void initCost() {
    cost[0] = 0;
    for(int i = 1; i <= N; i++) {
        cost[i] = INF;
    }
}

void buildGraph() {
    for(int i = 1; i <= N; i++) {
        dis[0][i] = node[i].price;
        for(int j = 0; j < node[i].itemCount; j++) {
            int id = node[i].itemNum[j];
            int val = node[i].itemPrice[j];
            dis[id][i] = val;
        }
    }
}

int dijkstra(int x) {
    memset(vis, false, sizeof(vis));
    initCost();
    for(int i = 1; i <= N; i++) {
        if(node[x].level <= node[i].level && node[i].level-node[x].level <= M) {
            cost[i] = dis[0][i];
        }
    }
    vis[0] = true;
    for(int i = 1; i <= N; i++) {
        int _min = INF;
        int p = -1;
        for(int j = 0; j <= N; j++) {
            if(!vis[j] && _min > cost[j]) {
                p = j;
                _min = cost[j];
            }
        }
        if(-1 == p || INF == _min)continue;
        vis[p] = true;
        for(int j = 0; j <= N; j++) {
            if(!vis[j] && cost[j] > cost[p]+dis[p][j] &&
               node[x].level <= node[j].level && node[j].level-node[x].level <= M) {
                cost[j] = cost[p]+dis[p][j];
            }
        }
    }
    return cost[1];
}

int main() {
    while(~scanf("%d%d", &M, &N)) {

        initDis();

        for(int i = 1; i <= N; i++) {
            scanf("%d%d%d", &node[i].price, &node[i].level, &node[i].itemCount);
            for(int j = 0; j < node[i].itemCount; j++) {
                scanf("%d%d", &node[i].itemNum[j], &node[i].itemPrice[j]);
            }
        }

        buildGraph();

        int ans = INF;
        for(int i = 1; i <= N; i++) {
            ans = min(dijkstra(i), ans);
        }

        printf("%d\n", ans);
    }
    return 0;
}
posted @ 2016-10-08 00:25  yinzm  阅读(1618)  评论(0编辑  收藏  举报