题目大意是说有N个物品,每个物品都有自己的价格,但同时某些物品也可以由其他的(可能不止一个)替代品,这些替代品的价格比较“优惠”,问怎么样选取可以让你的花费最少来购买到物品1
由于有N个物品,我们就可以把它们看作是N个点,从其他点到他的优惠关系视做边,又因为最后总是要找到物品1,然后由于题目是说,这条路劲上不能有两个的等级差超过M,所以我们可以枚举最小等级,将每个点视作最小等级,这样的话就不会掉解。枚举最小等级,然后把等级比他小或者不符合最大限制的点删去,然后在剩下的符合要求的点中再求dij即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define mp make_pair
#define x first
#define y second
const int INF=0x3f3f3f3f;
const int N=100+9;
int w[N][N],d[N],p[N],l[N];
bool vis[N];
int n;
int dij()
{
for(int i=1;i<=n;i++)d[i]=p[i];
for(int i=1;i<=n;i++){
int x,m=INF;
for(int j=1;j<=n;j++)if(!vis[j]&&d[j]<=m)m=d[x=j];
vis[x]=1;
for(int j=1;j<=n;j++)if(!vis[j])d[j]=min(d[j],d[x]+w[x][j]);
}
return d[1];
}
int main()
{
int m,X,T,V,minn=INF;
scanf("%d%d",&m,&n);
memset(w,0x3f,sizeof(w));
for(int i=1;i<=n;i++){
scanf("%d%d%d",&p[i],&l[i],&X);
while(X--){
scanf("%d%d",&T,&V);
w[T][i]=V;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(l[i]+m<l[j]||l[j]<l[i])vis[j]=1;
else vis[j]=0;
}
minn=min(minn,dij());
}
printf("%d\n",minn);
return 0;
}