昂贵的聘礼


算法:分两步:1、建图 2、从底到上逐个求每个点的最小费用。具体实现见程序注释。

#include <iostream>
#include<cstring>
#include<cmath>
using namespace std;

const int MAX=120;
int M,N,X,T,V;  //等级限制    物品总数       替代品总数        替代品的编号   优惠价格
int map[MAX][MAX];   //初始化全为0    map[i][j]=-1:i和j不能交换物品     map[i][j]=t:物品i可以用物品j加t金币替换
int topo[MAX];   //对于处理完的图,从底向上编号   topo[i]=j:第t个物品的编号为j
int visted[MAX];  //访问数组,初始化为0

//物品结构体
typedef struct NODE
{
    int level;  //等级
    int price;  //价格
} NODE;
NODE nodes[MAX];

int num=0;  //物品从底向上的序号,具体Topo函数

//采用深度优先的方式,对物品从底向上编号
void Dfs(int v)
{
    visted[v]=1;
    for (int i=1; i<=N; i++)
    {
        // 如果i未访问过 && u、i连通

        if (!visted[i] && map[v][i]>0)
        {
            Dfs(i);
        }
    }
    topo[num++]=v;
}

//计算完物品的编号后,从底向上计算物品的最小花费
void MinCost()
{
    int i,j;
    for (i=0; i<N; i++)
    {
        for (j=i+1; j<N; j++)
        {
            //以下的关系,要画个图,看清谁指向谁
            if (map[topo[j]][topo[i]]>0)
            {
                int temp=nodes[topo[i]].price+map[topo[j]][topo[i]];
                if ((temp<nodes[topo[j]].price))
                {
                    nodes[topo[j]].price=temp;
                }
            }
        }
    }
   cout<<nodes[1].price<<endl;
}

int main()
{
    int i,j;
    memset(map,0,sizeof(map));
    memset(visted,0,sizeof(visted));
    cin>>M>>N;
    for (i=1; i<=N; i++)
    {
        cin>>nodes[i].price>>nodes[i].level>>X; //价格 主人的地位等级 替代品总数
        for (j=1; j<=X; j++)
        {
           cin>>T>>V;  //替代品的编号   优惠价格
            map[i][T]=V;
        }
        //如果物品i不能和物品1交换,那么物品i可以直接不考虑:即便倒贴钱,也不能和物品1交换。直接把它加入黑名单
        if( abs(nodes[i].level-nodes[1].level) > M )
        {
            //把物品i加入黑名单:置物品i不能和任何物品交换
            for(j=1; j<N; j++)
            {
                map[j][i]=-1;
            }
        }
    }
    Dfs(1);  //从1开始,从底向上编号
    MinCost();  //求每个物品的最小花费
    return 0;
}

 

posted on 2013-11-19 21:26  天梦Interact  阅读(189)  评论(0编辑  收藏  举报