POJ 1062 昂贵的聘礼(dijkstra)

poj 1062

  • 题目大意
  • -

题目大意是说有N个物品,每个物品都有自己的价格,但同时某些物品也可以由其他的(可能不止一个)替代品,这些替代品的价格比较“优惠”,问怎么样选取可以让你的花费最少来购买到物品1

给一个图(N<100),每个节点有个等级值,给定编号为1的起点,求从起点出发的所有路径中的最短路,有一个限制条件是这条路径中每两个点的等级值相差不超过M。
- 分析
由于有等级值得限制,用N个节点的等级值来来枚举等级值得下界,运行N次dijkstra求出满足要求的最短路径。

  • 注意
    注意是每两个节点的等级值而不是有连接的两个节点。

  • 总结
    这道题特别要注意细节,WA了好多次,主要问题也处在等级值上。还有边的数组要开成n*n大小的。

  • 代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
const int INF=999999999;
int M,N;//等级差距限制和物品的总数
int P,L,X;//该物品的价格、主人的地位等级和替代品总数
int T,V;//替代品的编号和"优惠价格"
struct Edge
{
      int to;
      int next;
      int cost;
}edge[50000];
int Head[500];
int edgenum=0;
struct Node
{
      int id;
      int dist;
      int price;
      int states;
      bool operator < (const Node &rhs)const {
          return dist>rhs.dist;
      }
}node[500];
void Add_Edge(int u,int v,int t)
{
      edge[++edgenum].to=v;
      edge[edgenum].cost=t;
      edge[edgenum].next=Head[u];
      Head[u]=edgenum;
}
void Dijsktra(int m)
{
      for(int i=1;i<=N;i++)node[i].dist=INF;
      node[1].dist=0;
      if((node[1].states-m)>M || (node[1].states-m)<0)return;
      priority_queue<Node> Q;
      Q.push(node[1]);
      while(!Q.empty())
      {
            Node x=Q.top();
            Q.pop();
            for(int k=Head[x.id];k!=-1;k=edge[k].next)
            {
                  if( (node[edge[k].to].states-m)<=M  && (node[edge[k].to].states-m)>=0   &&    node[edge[k].to].dist > x.dist + edge[k].cost)//
                  {
                        node[edge[k].to].dist = x.dist + edge[k].cost;
                        Q.push(node[edge[k].to]);
                  }
            }
      }
}
int main()
{
     while(scanf("%d%d",&M,&N)!=EOF)
     {
        memset(edge,0,sizeof(edge));
        memset(Head,-1,sizeof(Head));
        edgenum=0;
        for(int i=1;i<=N;i++)
        {
             scanf("%d%d%d",&P,&L,&X);
             node[i].price=P;
             node[i].states=L;
             node[i].id=i;
             for(int j=1;j<=X;j++)
             {
                   scanf("%d%d",&T,&V);
                   Add_Edge(i,T,V);
             }
        }
        int ans=INF;
        for(int i=1;i<=N;i++)
        {
            Dijsktra(node[i].states);//枚举最低的等级
            for(int i=1;i<=N;i++)
            {
                if(ans>node[i].dist+node[i].price)ans=node[i].dist+node[i].price;
            }
        }
        printf("%d\n",ans);
      }
      return 0;


}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值