POJ 1062: 昂贵的聘礼

来源:互联网 发布:java积分下载上传系统 编辑:程序博客网 时间:2024/05/29 02:42

题目链接:http://poj.org/problem?id=1062


题目大意:现有N个物品,每个物品都有对应的价格P,主人的地位等级L,以及一系列的替代品Ti和该替代品所对应的"优惠"Vi(如果用替代品Ti和来换,就能获得优惠"Vi",优惠不能叠加)。如果两人地位等级差距超过了M,就不能交易以及"间接交易"。问获得物品1最少需花费的金币数是多少。


算法:

显然,左右经过的点,一定在一个长度为m的区间内,

那么我枚举这个区间的左界,做最短路即可。

构图时,边权就是原价与优惠价格 Vi的差值


代码如下:

#include<cstdio>#include<iostream>#include<sstream>#include<cstdlib>#include<cstring>#include<string>#include<climits>#include<cmath>#include<algorithm>#include<queue>#include<vector>#include<stack>#include<set>#include<map>#define INF 0x3f3f3f3f#define eps 1e-8using namespace std;const int MAXN=110;int d[MAXN],val[MAXN],level[MAXN];vector<pair<int,int > >M[MAXN];int main() {    int m,n;    while(~scanf("%d%d",&m,&n)) {        for(int i=0; i<n; i++) {            M[i].clear();        }        for(int i=0; i<n; i++) {            int num;            scanf("%d%d%d",&val[i],&level[i],&num);            while(num--) {                int x,v;                scanf("%d%d",&x,&v);                x--;                M[x].push_back(make_pair(i,v));            }        }        int ans=val[0];        for(int l=level[0]-m; l<=level[0]; l++) {            int r=l+m;            queue<int>q;            for(int i=0; i<n; i++) {                if(level[i]<l||level[i]>r) {                    continue;                }                q.push(i);                d[i]=val[i];            }            while(!q.empty()) {                int u=q.front();                q.pop();                for(int i=0; i<M[u].size(); i++) {                    int v=M[u][i].first;                    if(level[v]<l||level[r]>r) {                        continue;                    }                    if(d[v]>d[u]+M[u][i].second) {                        d[v]=d[u]+M[u][i].second;                        q.push(v);                    }                }            }            ans=min(ans,d[0]);        }        printf("%d\n",ans);    }    return 0;}




原创粉丝点击