题目链接:点我啊╭(╯^╰)╮
题目大意:
n n n件物品,每件物品有自己的价格 P P P,物品的等级 L L L,可以被替代的物品数量 X X X,每件物品的X行给出能替代的物品编号和替换所需要的金币,同时物品进行交换的时候等级差不能超过 M M M,问花费的最小金币数量???
解题思路:
明显,怎么建图是本题的难点,既然每件物品都有本身的价值,我们不妨另外设置一个原点 0 0 0,原点到 n n n 个物品的边权即为物品的价值,那么问题就在于,原点是没有等级的,那么怎么来限制题目所要求的等级差呢???
看了别人的想法才知道,可以枚举 r a n k [ 0 ] rank[0] rank[0]为 n n n件物品的等级,同时假设 r a n k [ 0 ] rank[0] rank[0]即为所有物品里的最低等级,那么根据题目要求,所有交换都要满足 r a n k [ k ] − r a n k [ 0 ] ≥ M rank[k]-rank[0]≥M rank[k]−rank[0]≥M
代码思路:
跑 n 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);
}