您的位置:首页 > 其它

POJ 1062 昂贵的聘礼 Dijkstra

2011-07-28 23:36 225 查看
好不容易看到大段的中文啊..这不是爱情买卖..是婚姻买卖啊...
一开始困惑怎么解决等级交换问题,后来看了大牛的思路,才知道原来是枚举交换范围加求最短路啊..果然巧妙.
假设酋长的等级是N,等级交换差距限制是M,那么探险家只能和N-M到N+M等级范围内的人交换物品
但是并不代表探险家能在这个范围内自由交换,比如说,你和N-M等级的人交换了,N+M等级的人就不会和你换了..
但是可以保证的是(N-M,N),(N-M+1.N+1)......(N,N+M)这些分范围内的人都是能自由交换的,彼此最大等级差是M..
因此只要枚举这些区间,求最短路,路径中的点必须符合等级范围即可.
之所以是求最短路,是因为在换的过程中尽量优惠,将优惠后价格加起来,看到每一点优惠后的价格最低是多少就可以了,注意最后一件物品是要购买的,因此要将所有点的值加上该点对应商品的价值求最小值.
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#define INF 1e8
using namespace std;
typedef pair<int,int> pa;
struct point{
int v;//价值
int l;//等级
}p[105];//点
int map[105][105];//边
int value[105];
int done[105];
int m,n;
void init(){//初始化邻接矩阵
for(int i=0;i<105;i++){
for(int j=0;j<105;j++){
map[i][j]=(i==j)?0:INF;
}
}
}
int dij(int level){
for(int i=1;i<=n;i++){
value[i]=(i==1)?0:INF;
}
memset(done,0,sizeof done);
priority_queue<pa,vector<pa>,greater<pa> > q;//使用优先队列实现Dijkstra
q.push(make_pair(value[1],1));
while(!q.empty()){
int x=q.top().second;
q.pop();
if(done[x])continue;
done[x]=1;
for(int i=1;i<=n;i++){
if(map[x][i]!=0&&p[i].l>=level&&p[i].l<=level+m&&value[i]>value[x]+map[x][i]){
value[i]=value[x]+map[x][i];
q.push(make_pair(value[i],i));
}
}
}
int m=INF;
for(int i=1;i<=n;i++){//还要加上买该物品的值
value[i]+=p[i].v;
//printf("  %d\n",value[i]);
m=min(m,value[i]);
}
return m;
}
int main(){
//freopen("in.txt","r",stdin);
scanf("%d%d",&m,&n);
int ed,te,tv;
for(int i=1;i<=n;i++){
scanf("%d%d%d",&p[i].v,&p[i].l,&ed);
for(int j=0;j<ed;j++){
scanf("%d%d",&te,&tv);
map[i][te]=tv;
}
}
int res=INF;
for(int i=p[1].l-m;i<=p[1].l;i++){//枚举可能的范围,分别求最小值
res=min(res,dij(i));
}
printf("%d\n",res);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: