poj1062 Bellman 昂贵的聘礼

题目链接:点击打开链接

这是一道很有意思,也很坑的题。

我是以每个部落的人为节点,以他能交易的东西为边。

等级的判断非常重要,枚举的时候,交易双方的等级都必须在范围内。

附上大牛的测试数据
测试数据1:  
1 4  
10000 3 2  
2 8000  
3 5000  
1000 2 1  
4 200  
3000 2 1  
4 200  
50 2 0  
  
5250  
  
测试数据2:  
1 5  
10000 3 4  
2 3000  
3 2000  
4 2000  
5 9000  
8000 2 3  
3 5000  
4 2000  
5 7000  
5000 1 0  
2000 4 1  
5 1900  
50 1 0  
  
4000  
测试数据3:  
3 8  
10000 3 6  
2 3000  
3 2000  
4 2000  
5 9000  
7 1000  
8 5008  
8000 2 3  
3 5000  
4 2000  
5 7000  
5000 1 1  
6 1000  
2000 4 1  
5 1900  
50 1 0  
5000 1 1  
7 4007  
2000 4 1  
5 1900  
80 3 0  
  
2950  
测试数据4:  
1 10  
1324 0 0  
1234 0 0  
255 0 0  
67 0 0  
56 0 0  
2134 0 0  
456 0 0  
2345 0 0  
67 0 0  
6436 0 0  
  
1324  
  
测试数据5:  
1 4  
10000 3 2  
2 1  
3 3  
1000 2 2  
4 1  
3 1  
1000 3 1  
4 2  
100 4 0  
  
105  
测试数据6:  
3 5  
10000 3 4  
2 3000  
3 2000  
4 2000  
5 9000  
8000 2 3  
3 5000  
4 2000  
5 7000  
5000 1 0  
2000 4 1  
5 1900  
50 1 0  
  
3950 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
using namespace std;
struct ab{
    int u,v,p;//r:等级
}ex[25500];
int node[25500],ranks[25500],rankg[25500];
int n,m,w,cnt;
int bellman(int le){
    int check;
    int dis[25500];
    memset(dis,1,sizeof(dis));
    dis[1]=node[1];

    for(int k=1; k<=n-1; k++) //算法核心
    {
        check=0;

        for(int i=1; i<=cnt; i++)
            if((ranks[ex[i].v]<=m+le&&ranks[ex[i].v]>=le)&&(ranks[ex[i].u]<=m+le&&ranks[ex[i].u]>=le)&&dis[ex[i].v]>dis[ex[i].u]+ex[i].p+node[ex[i].v]){
                dis[ex[i].v]=dis[ex[i].u]+ex[i].p+node[ex[i].v];   //交易的双方都必须在范围内
                check=1;
            }  //进行松弛操作

        if(check==0) break;//检测dis是否有更新,没有就退出循环
        //for(int i=1; i<=cnt; i++) printf("%d ",dis[i]); printf("\n");
    }

    int mins=99999999;
    for(int i=1; i<=cnt; i++){
        if(mins>dis[i])
            mins=dis[i];
    }
    return mins;
}
int main()
{
    int p,l,x,t,v;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(ex,0,sizeof(ex));
        memset(node,0,sizeof(node));
        cnt=1;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&p,&l,&x);
            node[i]=p; ranks[i]=l;
            for(int j=1;j<=x;j++){
                scanf("%d%d",&t,&v);
                ex[cnt].u=i;
                ex[cnt].v=t;
                ex[cnt].p=(v-p); //建图,边为负权
                cnt++;
            }
        }
        int minsum=9999999;
        for(int i=ranks[1]-m;i<=ranks[1];i++){ //枚举等级范围,取最小
            //cout<<rankg[i]<<endl;
            int ss=bellman(i);
            if(ss<minsum) minsum=ss;
        }


            printf("%d\n",minsum);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值