POJ1062 昂贵的聘礼 图论(Dijkstra)


刚刚学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 matri	x
	for (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 input
	for (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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值