poj1062

题意:每个人都有一个物品,对应一定的钱数,想要得到此物品可以直接出钱,也可以通过用其他人的物品并添加一些钱来交换,问要得到酋长的物品最少需要多少钱?另外,每个人都有一个等级,要求和你交易的人中不能有任何两人的等级相差m以上。

分析:我们可以把本题理解为,我们要买一号物品,而一个物品的一部分价值可以转化为别的物品,我们通过购买别的物品和加钱来购买获得一号物品。所以我们可以把需要加的钱数作为该物品到别的物品的一条边,走过这条边,我们要花一些钱,然后我们只需要购买现在所在结点的物品即可。这样就把问题转化为最短路问题,用dijkstra就可以了。

本题还有个等级制度的问题。我们可以每次枚举一个宽为m的等级区间,忽略不在区间内的点,进行dijkstra。

我wrong answer是因为第一次没处理起始点不在枚举的区间内的情况。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 101, inf = 1000000000;

struct Item
{
	int p, l;
} item[maxn];

struct Edge
{
	int v, w;
	Edge()
	{
	}
	Edge(int vv, int ww) :
		v(vv), w(ww)
	{
	}
} e[maxn * maxn];

int map[maxn], level[maxn], levelnum = 0, dist[maxn];
int n, m;
bool vis[maxn];

void dijkstra(int floor)
{
	int best = 0, besti = 0;
	int d[maxn];

	for (int i = 0; i <n; i++)
	{
		d[i] = inf;
		vis[i] = false;
	}
	d[0] = 0;
	while (besti != -1)
	{
		vis[besti] = true;
		for (int i = map[besti]; i < map[besti + 1]; i++)
		{
			if (d[e[i].v] > best + e[i].w && item[e[i].v].l >= floor && item[e[i].v].l <= floor + m)
			{
				d[e[i].v] = best + e[i].w;
			}
		}
		best = inf;
		besti = -1;
		for (int i = 0; i < n; i++)
			if (!vis[i] && d[i] < best)
			{
				best = d[i];
				besti = i;
			}
	}
	for (int i = 0; i < n; i++)
		if (dist[i] > d[i])
			dist[i] = d[i];
}

int main()
{
	//freopen("D:\\t.txt", "r", stdin);
	scanf("%d%d", &m, &n);
	for (int i = 0; i < n; i++)
		dist[i] = inf;
	map[0] = 0;
	for (int i = 0; i < n; i++)
	{
		int temp;
		scanf("%d%d%d", &item[i].p, &item[i].l, &temp);
		level[levelnum++] = item[i].l;
		map[i + 1] = map[i] + temp;
		for (int j = 0; j < temp; j++)
		{
			int a, b;
			scanf("%d%d", &a, &b);
			a--;
			e[map[i] + j] = Edge(a, b);
		}
	}
	sort(level, level + levelnum);
	levelnum = unique(level, level + levelnum) - level;
	for (int i = 0; i < levelnum; i++)
		if (item[0].l >= level[i] && item[0].l <= level[i] + m)
		dijkstra(level[i]);
	int ans = inf;
	for (int i = 0; i < n; i++)
		if (ans > dist[i] + item[i].p)
			ans = dist[i] + item[i].p;
	printf("%d\n", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/rainydays/p/1948670.html