题目大意是说有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 ",minn); return 0; }