中文题,就不贴题了。
一开始想一发过,记录交换的最小等级和最大等级,才知道并没有这么简单,因为这个等级限制是不是只限于当前交换的两个人,而是交换的所有人,最后实在想不起来什么好办法,就在网上发现采用枚举,即假设酋长等级为5,等级限制为2,那么需要枚举等级从3~5,4~6,5~7,然后注意就是是单向路径,一开始以为枚举会超时,其实想多了,很快就过了。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int Lt[105]; //等级
int dis[105]; //金币
int book[105]; //标记
int e[105][105];//e[i][j] 表示i交换j需要多少钱
void init(int n) { //初始化
memset(Lt, 0, sizeof(Lt)); //一开始的等级
for(int i = 0; i <= n; i++) {
for(int j = 0; j <= n; j++) {
if(i == j) e[i][j] = 0;
else e[i][j] = inf;
}
}
}
int Dijkstra(int n) {
for(int i = 1; i <= n; i++) {
dis[i] = e[0][i]; //初始的时候每个物品的价钱
}
for(int i = 0; i < n; i++) {
bool flag = false;
int mn = inf, p;
for(int j = 1; j <= n; j++) {
if(!book[j] && mn > dis[j]) {
mn = dis[j];
p = j;
flag = true;
}
}
if(!flag) break;
book[p] = 1;
for(int j = 1; j <= n; j++) {
if(book[j]) continue;
if(dis[j] > (dis[p] + e[p][j])) {
dis[j] = dis[p] + e[p][j];
}
}
}
return dis[1];
}
int main() {
int M, N; //分别代表等级差距限制,物品的总数
int P, L ,X; //物品价格, 主人的地位, 代替品总数
int T, V; //代替品编号, 优惠价格
while(~scanf("%d %d", &M, &N)) {
init(N); //初始化
for(int i = 1; i <= N; i++) {
scanf("%d %d %d", &P, &L, &X);
e[0][i] = P; //初始化,便于每次更新dis[i]
Lt[i] = L; //将i的等级记录下来
while(X--) {
scanf("%d %d", &T, &V);
e[T][i] = V; //T交换i
}
}
int mn = inf; //找最小值
for(int i = 0; i <= M; i++) {
memset(book, 0, sizeof(book));
for(int j = 1; j <= N; j++) {
if(Lt[j] < Lt[1]-i || Lt[j] > Lt[1]+M-i) //可以满足交换
book[j] = 1;
}
mn = min(mn, Dijkstra(N));
}
printf("%d\n", mn);
}
return 0;
}
/*
1 4
10000 3 2
2 1
3 3
1000 2 2
4 1
3 1
1000 3 1
4 2
100 4 0
105
*/