本题题意比较难懂,说白了就是兑换的过程中,必须满足主人的最高等级-最低等级<=M,否则不能进行兑换。由于M较小,可以枚举等级的区间。
举个例子:假设主人等级为3,M为2。
那兑换的过程中每个人的等级一定在[1,3] 或 [2,4] 或 [3,5]中的某个区间中。
枚举这个区间,然后倒着求最短路即可。
注意本题是有向图。
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <assert.h>
#include <time.h>
typedef long long LL;
const int INF = 500000001;
const double EPS = 1e-9;
const double PI = acos(-1.0);
using namespace std;
int graph[105][105];
int vis[105], val[105], M, N;
void init()
{
for(int i = 0; i < 101; i++)
{
for(int j = 0; j < 101; j++)
{
graph[i][j] = INF;
}
}
}
void Dijkstra()
{
for(int i = 2; i <= 100; i++)
{
val[i] = graph[1][i];
if(!vis[i]) val[i] = INF;
}
for(int i = 2; i <= N; i++)
{
int k = -1, minn = INF;
for(int j = 2; j <= N; j++)
{
if(vis[j] == -1 && minn > val[j])
{
k = j;
minn = val[j];
}
}
if(k == -1) break;
vis[k] = 0;
for(int j = 2; j <= N; j++)
{
if(vis[j] == -1 && val[k] + graph[k][j] < val[j])
{
val[j] = val[k] + graph[k][j];
}
}
}
}
int main()
{
#ifdef _Test
freopen("test0.in", "r", stdin);
freopen("test0.out", "w", stdout);
srand(time(NULL));
#endif
int P[1000], L[1000], X, T, V;
while(~scanf("%d %d", &M, &N))
{
init();
for(int i = 1; i <= N; i++)
{
scanf("%d %d %d", &P[i], &L[i], &X);
for(int j = 0; j < X; j++)
{
scanf("%d %d", &T, &V);
graph[i][T] = V;
}
}
int ans = P[1];
for(int i = max(L[1] - M, 0); i <= L[1]; i++)
{
memset(vis, -1, sizeof(vis));
for(int ii = 2; ii <= N; ii++)
{
if(L[ii] < i || L[ii] > i + M)
{
vis[ii] = 0;
}
}
Dijkstra();
for(int j = 2; j <= N; j++)
{
ans = min(ans, val[j] + P[j]);
}
}
printf("%d\n", ans);
}
return 0;
}