POJ-1062___昂贵的聘礼——枚举 + 最短路

题目链接:点我啊╭(╯^╰)╮

题目大意:

     n n 件物品,每件物品有自己的价格 P P ,物品的等级 L L ,可以被替代的物品数量 X X ,每件物品的X行给出能替代的物品编号和替换所需要的金币,同时物品进行交换的时候等级差不能超过 M M ,问花费的最小金币数量???

解题思路:

    明显,怎么建图是本题的难点,既然每件物品都有本身的价值,我们不妨另外设置一个原点 0 0 ,原点到 n n 个物品的边权即为物品的价值,那么问题就在于,原点是没有等级的,那么怎么来限制题目所要求的等级差呢???

    看了别人的想法才知道,可以枚举 r a n k [ 0 ] rank[0] n n 件物品的等级,同时假设 r a n k [ 0 ] rank[0] 即为所有物品里的最低等级,那么根据题目要求,所有交换都要满足 r a n k [ k ] r a n k [ 0 ] M rank[k]-rank[0]≥M

代码思路:

    跑 n n 遍迪杰斯特拉,取最小值

核心:枚举最小值来解决等级问题

#include<bits/stdc++.h>
using namespace std;

const int INF = 0x3F3F3F3F;
const int N = 105;
int m, n, mp[N][N];
int dis[N], vis[N], rank[N];

void init() {
	for (int i=0; i<=n; i++) {
		for (int j=0; j<=n; j++) {
			if (i == j)	mp[i][j] = 0;
			else mp[i][j] = INF;
		}
		dis[i]=INF;
	}
}

bool rk(int i, int j){
	return rank[i]<=rank[j] && (rank[j]-rank[i])<=m;
}

void creatgraph() {
	int t1, t2, t3;
	for (int i=1; i<=n; i++) {
		scanf("%d%d%d", &t1, &t2, &t3);
		mp[0][i] = t1;
		rank[i] = t2;
		for (int j=1; j<=t3; j++) {
			scanf("%d%d", &t1, &t2);
			mp[t1][i] = t2;	
		}
	}
}

int dijkstra(int st) {
	memset(vis, 0, sizeof(vis));
	for (int i=0; i<=n; i++) dis[i] = mp[st][i];
	vis[st] = 1;
	for (int i=1; i<=n; i++) {	
		/*找出离起点最近的点*/
		int minn = INF, k = -1;
		for (int j=1; j<=n; j++) {
			if (!vis[j] && dis[j]<minn) {
				minn = dis[j];
				k = j;
			}
		}
		if(k==-1) break;
		vis[k] = 1;
		
		if(!rk(0,k)) continue;
		for (int j=1; j<=n; j++) {	//松弛操作,找到媒介使得出现新的最短路
			if (!vis[j] && dis[k]+mp[k][j] < dis[j] && rk(0,j))
				dis[j] = dis[k] + mp[k][j];
		}
	}
	return dis[1];
}

int main() {
	scanf("%d%d", &m, &n);	
	init();	//初始化地图
	creatgraph();	//建图
	int ans = INF;
	for(int i=1; i<=n; i++){
		rank[0] = rank[i];
		ans = min(ans, dijkstra(0));
	}
	printf("%d\n", ans);
}

猜你喜欢

转载自blog.csdn.net/Scar_Halo/article/details/83546038
今日推荐