题目链接:点击打开链接
题目大意:一共有n种货物,如果想获取一种货物,每一个货物都有自己的等级为l,有两种方法,一是支付对应价值的金币,还有一种是支付另一种货物加上一定的金币。如果整个交易过程中有两种货物等级差大于m,交易就不合法。问要买第一种货物最少需要花多少金币。
数据范围为n<=100.
图论题,观察以后就可以发现,每一次用物品交易的时候,会有一部分的交易金是固定的。整个交易完成后,支付的金币为交易过程的交易金加上最后一个物品的价值。所以是一个单源最短路问题,用spfa或者dijk。
为了保证所有的交易都合法,我们可以枚举一个包含第一个物品等级(因为从第一个物品开始)的长度为m的等级区间,无视不在这个区间内的物品,这样就能得到最优解。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <vector>
#include <algorithm>
#define N 1005
using namespace std;
typedef struct{
int p,l;
}item;
typedef struct{
int t,v;
}trade;
item it[105];
vector<trade>p[105];
int q[N],n,m;
int price[105];
bool vis[105];
int spfa(){
int u,v,f,r,pp,left,right,ans;
ans = 0x3f3f3f3f;
memset(vis,0,sizeof(vis));
for(int i = 0;i <= m;i++){
memset(price,0x3f,sizeof(price));
left = it[1].l - m + i;
right = left + m;
f = 0;
r = 1;
q[0] = 1;
vis[1] = 1;
price[1] = 0;
while(f!=r){
u = q[f++];
f%=N;
vis[u] = 0;
for(int i = 0;i < p[u].size(); i++){
v = p[u][i].t;
pp = p[u][i].v;
if( it[v].l>=left && it[v].l<=right && price[v] > price[u] + pp){
price[v] = price[u] + pp;
if(!vis[v]){
vis[v] = 1;
q[r++] = v;
r%=N;
}
}
}
}
for(int i = 1;i <= n;i++) if(price[i] + it[i].p <ans) ans = price[i] + it[i].p;
}
return ans;
}
int main(){
int pr,l,x,t,v,ans;
trade tmp;
cin>>m>>n;
for(int i = 1; i <= n;i++){
cin>>pr>>l>>x;
it[i].p = pr;
it[i].l = l;
for(int j = 0;j < x;j++){
cin>>t;
cin>>v;
tmp.t = t;
tmp.v = v;
p[i].push_back(tmp);
}
}
ans = spfa();
printf("%d\n",ans);
return 0;
}