zoukankan      html  css  js  c++  java
  • POJ1062:昂贵的聘礼(枚举+迪杰斯特拉)

    http://poj.org/problem?id=1062

    Description

    年轻的探险家来到了一个印第安部落里。在那里他和酋长的女儿相爱了,于是便向酋长去求亲。酋长要他用10000个金币作为聘礼才答应把女儿嫁给他。探险家拿不出这么多金币,便请求酋长降低要求。酋长说:"嗯,如果你能够替我弄到大祭司的皮袄,我可以只要8000金币。如果你能够弄来他的水晶球,那么只要5000金币就行了。"探险家就跑到大祭司那里,向他要求皮袄或水晶球,大祭司要他用金币来换,或者替他弄来其他的东西,他可以降低价格。探险家于是又跑到其他地方,其他人也提出了类似的要求,或者直接用金币换,或者找到其他东西就可以降低价格。不过探险家没必要用多样东西去换一样东西,因为不会得到更低的价格。探险家现在很需要你的帮忙,让他用最少的金币娶到自己的心上人。另外他要告诉你的是,在这个部落里,等级观念十分森严。地位差距超过一定限制的两个人之间不会进行任何形式的直接接触,包括交易。他是一个外来人,所以可以不受这些限制。但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。因此你需要在考虑所有的情况以后给他提供一个最好的方案。 
    为了方便起见,我们把所有的物品从1开始进行编号,酋长的允诺也看作一个物品,并且编号总是1。每个物品都有对应的价格P,主人的地位等级L,以及一系列的替代品Ti和该替代品所对应的"优惠"Vi。如果两人地位等级差距超过了M,就不能"间接交易"。你必须根据这些数据来计算出探险家最少需要多少金币才能娶到酋长的女儿。 

    Input

    输入第一行是两个整数M,N(1 <= N <= 100),依次表示地位等级差距限制和物品的总数。接下来按照编号从小到大依次给出了N个物品的描述。每个物品的描述开头是三个非负整数P、L、X(X < N),依次表示该物品的价格、主人的地位等级和替代品总数。接下来X行每行包括两个整数T和V,分别表示替代品的编号和"优惠价格"。

    Output

    输出最少需要的金币数。

    Sample Input

    1 4
    10000 3 2
    2 8000
    3 5000
    1000 2 1
    4 200
    3000 2 1
    4 200
    50 2 0
    

    Sample Output

    5250
    题目解析:
    1.注意等级限制,我本来以为只有在相邻的两个人物中有等级的限制,其实在你需要交换的所有人都有等级的限制。
    2.建图要建有向图,不是无向图。
    3.
    我们可以把本题理解为,我们要买一号物品,而一个物品的一部分价值可以转化为别的物品,我们通过购买别的物品和加钱来购买获得
    一号物品。所以 我们可以把需要加的钱数作为该物品到别的物品的一条边,走过这条边,我们要花一些钱,然后我们只需要购买现在所
    在结点的物品即可。这样就把问题转化为最短 路问题,用dijkstra就可以了。本题还有个等级制度的问题。我们可以每次枚举一个宽
    为m的等级区间,忽略不在区间内的点,进行dijkstra。
    4.需要建立一个超级源点0来存储到每个物品的价钱。
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    int map[101][101],dis[101],v[101];
    int m,n,f[101];
    void dj(int l,int r)
    {
        int min,k;
        for(int i=0; i<=n; i++)
        {
            dis[i]=inf;
            v[i]=0;
        }
        v[0]=1;
        for(int i=0; i<=n; i++)
        {
            if(f[i]>=l&&f[i]<=r)
                dis[i]=map[0][i];
        }
        while(1)
        {
            min=inf;
            for(int i=0; i<=n; i++)
            {
                if(v[i]==0&&min>dis[i])
                {
                    min=dis[i];
                    k=i;
                }
            }
            v[k]=1;
            if(k==1)
                return ;
            for(int i=0; i<=n; i++)
            {
                if(v[i]==0&&f[i]>=l&&f[i]<=r&&dis[i]>map[k][i]+dis[k])
                {
                    dis[i]=map[k][i]+dis[k];
                }
            }
        }
        return ;
    }
    int main()
    {
        int p,w,x,y;
        while(scanf("%d%d",&m,&n)!=EOF)
        {
            for(int i=0; i<=n; i++)
            {
                for(int j=0; j<=n; j++)
                {
                    map[i][j]=inf;
                }
                map[i][i]=0;
            }
            for(int i=1; i<=n; i++)
            {
                scanf("%d%d%d",&p,&f[i],&w);
                map[0][i]=p;
                while(w--)
                {
                    scanf("%d%d",&x,&y);
                    if(map[x][i]>y)
                    {
                        map[x][i]=y;
                    }
                }
            }
            int max=inf;
            for(int i=f[1]-m; i<=f[1]; i++)
            {
                dj(i,i+m);
                if(max>dis[1])
                    max=dis[1];
            }
            cout<<max<<endl;
        }
        return 0;
    }
  • 相关阅读:
    C#for循环——迭代法、穷举法
    C#循环语句
    C#算数运算符、关系运算符、逻辑运算符、语句
    C#visual2012基本操作、数据类型、类型转换
    C#进制转化
    Ajax用法
    《四》JAVA 字符输入输出流
    《三》Java IO 字节输入输出流
    《二》Java IO 流的分类介绍
    《一》File 类的介绍
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/3973093.html
Copyright © 2011-2022 走看看