POJ1062 昂贵的聘礼 图论(Dijkstra)

来源:互联网 发布:阿里云服务器好卡 编辑:程序博客网 时间:2024/06/05 17:18


刚刚学dijkstra算法,卧槽痛苦的干了一下午这个题,从开始学,到模仿别人的代码,到改代码的bug等等一系列的事情。

终于感觉有点对这个算法入门了哈哈。


题目概述:

题目是说有一个探险家想要娶酋长的女儿,但是原始部落嘛就需要聘礼,然后幸好的是这个金币可以由另一些不值金币这些钱的货物抵价,那么我们的探险家先生就拜托我们算一算自己最少花多少钱才能娶回酋长的女儿。然后这个部落的蛋疼之处就在于等级观念,等级差了很多的人是不能直接或者间接互相交易的。

等级限制,哪些物品能够抵价,数据范围请移步:

http://poj.org/problem?id=1062

算法思想:

每一个货物模型成一个端点,端点的性质有等级,可替代物,以及自身价格。

每一个替代方式模型成一条边,边的性质为花多少钱。

这道题的路径就相当于是从最初的位置一直往下搜索,总共花的钱应该是所有路径的钱加上最后一个结点自身的价值嗯就这样。

然后关于等级限制的条件,用枚举法,比如说酋长等级是4,等级限制是2,那么我们就要取等级为[2,4],[3,5],[4,6]的三个区间,每一个区间实际上对应着一副子图,对子图进行搜索就好了。

剩余的部分就是dijkstra的实现了。

代码部分:

#include <iostream>#include <string.h>using namespace std;int m, n, level_limit;int w[117][117];int value[117], level[117], dis[117], replace_num;bool vis[117], satis_level[117];int INF = 100000000;int dijkstra() {int mini_cost = INF;memset(vis, 0, sizeof(vis));for (int i = 1; i <= n; i++){dis[i] = INF;}dis[1] = 0;for (int i = 1; i <= n; i++){int x = 1; int min = INF;for (int j = 1; j <= n; j++){if (!vis[j] && satis_level[j] && dis[j] <= min) {x = j;min = dis[j];}}vis[x] = 1;for (int j = 1; j <= n; j++){if (satis_level[j]) {dis[j] = dis[j] > (dis[x] + w[x][j]) ? (dis[x] + w[x][j]) : dis[j];}}}for (int i = 1; i <= n; i++) {dis[i] = dis[i] + value[i];mini_cost = dis[i] < mini_cost ? dis[i] : mini_cost;}return mini_cost;}int main() {cin >> m >> n;level_limit = m;// initialization of matrixfor (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (i == j) w[i][j] = 0;else w[i][j] = INF;}}// initialize inputfor (int i = 1; i <= n; i++){cin >> value[i] >> level[i] >> replace_num;for (int j = 1; j <= replace_num; j++){int y, value;cin >> y >> value;w[i][y] = value;}}int King_level = level[1];int res = INF;for (int i = 0; i <= level_limit; i++){memset(satis_level, 0, sizeof(satis_level));for (int j = 1; j <= n; j++){if (level[j] >= King_level - level_limit + i && level[j] <= King_level + i){satis_level[j] = true;}}res = res > dijkstra() ? dijkstra() : res;}cout << res << endl;return 0;}


0 0