- 题目大意
有N个物品,每个物品都有自己的价格,但同时某些物品也可以由其他的(可能不止一个)替代品,这些替代品的价格比较“优惠”,问怎么样选取可以让你的花费最少来购买到物品1。
- 解题思路
我们就可以把N个物品看作是N个点,从其他点到他的关系视做边,又因为最后总是要找到物品1,所以可以看作是从起点0,到将物品1作为终点的最小路劲。然后由于题目是说,这条路劲上不能有两个的等级差超过M,所以我们可以枚举最小等级,将每个点视作最小等级,这样的话就不会掉解。又由于我们是枚举的最小等级,所以源点0到其他每个点的边的权值就要赋值为那个点的价格,降等级比最小等级要大,或者差距大于M的其他点标记为不合法(也就是不可以走),然后在从合法的路径中找出最小花费。
- 代码
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=500; const int INF=0x3f3f3f; int vis[N],level[N],money[N],d[N]; int g[N][N]; int n,m,cnt; void init() { memset(money,0,sizeof(money)); memset(level,0,sizeof(level)); for(int i=0;i<=n;i++) { for(int j=0;j<=n;j++) g[i][j]=INF; } } int dijkstra() { memset(d, INF, sizeof(d)); for(int i=1;i<=n;i++) d[i]=money[i]; while(1) { int v = -1; for(int u = 1; u <= n; u++) { if(!vis[u] && (v == -1 || d[u] < d[v])) v = u; } if(v == -1) break; vis[v] = 1; for(int u = 1; u <= n; u++) { if(!vis[u] && d[u] > d[v] + g[v][u]) { d[u] = d[v] + g[v][u]; } } } return d[1]; } int main() { int x,a,b; scanf("%d%d",&m,&n); init(); for(int i=1;i<=n;i++) { scanf("%d%d%d",&money[i],&level[i],&x); while(x--) { scanf("%d%d",&a,&b); g[a][i]=b; } g[0][i]=money[i]; } cnt=INF; for(int i=1;i<=n;i++) { int minn=level[i]; for(int j=1;j<=n;j++) { if(level[j]-minn>m||minn>level[j]) vis[j]=1; else vis[j]=0; } cnt=min(cnt,dijkstra()); } printf("%d\n",cnt); return 0; }