- 题目大意
- -
题目大意是说有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;
}