B - 昂贵的聘礼 (POJ - 1062)
- 题目大意
有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;
}

浙公网安备 33010602011771号