昂贵的聘礼

F题倒过来单向给数组赋值,如money[4][3]表示有了4物品得到3物品需要给的金钱,0为超级起点,money[0][1]表示直接得到1物品需要的金钱,图构建好了,我也是用Floyd算法直接计算得到1物品需要的最少金钱。但是我调试了很多次也没找出来哪里错了。

#include <iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#define INF 9999999
using namespace std;
struct goods
{
    int price,level,repnum,need[105];
}a[105];


int main()
{
    int allnum,limit,charge,num,b[105],i,j=0,money[105][105],k;
    scanf("%d%d",&limit,&allnum);
    memset(a,0,sizeof(a));
    for(i=0;i<=allnum;i++)
    {
        for(j=0;j<=allnum;j++)
        {
             money[i][j]=(i==j?0:INF);
        }
    }
    for(i=1;i<=allnum;i++)
    {
        scanf("%d%d%d",&a[i].price,&a[i].level,&a[i].repnum);
        for(j=0;j<a[i].repnum;j++)
        {
            scanf("%d%d",&num,&charge);
            b[num]=charge;
a[i].need[num]=1;
        }
    }
    for(i=allnum;i>0;i--)
        {
            for(j=i-1;j>0;j--)
            {
                if(fabs(a[1].level-a[i].level)<=limit&&a[j].need[i]==1)
                {
money[i][j]=b[i];
}
            }
        }
        for(i=0,j=1;j<=allnum;j++)
        {
            money[i][j]=a[j].price;          
        }
for(k=0;k<=allnum;k++)
{
            for(i=0;i<=allnum;i++)
{
for(j=0;j<=allnum;j++)
{
if(money[i][j]>money[i][k]+money[k][j])
money[i][j]=money[i][k]+money[k][j];
}
}
}
    printf("%d\n",money[0][1]);
    return 0;
}

用Floyd暂时还没有写出来,但是仿照着别人的dij算法把这道题做了主要欠考虑的地方是等级范围,应该是(k-m,k),中间只应该有m个数,而不是(k-m,k+m)

#include <iostream>                         //dij算法昂贵的聘礼

#include<cstring>

#include<cstdio>

#define INF 0x7f7f7f7f

#define maxn 1005

 

using namespace std;

int dis[maxn];

bool vis[maxn];

int money[maxn][maxn];

int limit,allnum,charge,num,price[maxn],level[maxn],rep[maxn];

void init()

{

    memset(dis,INF,sizeof(dis));

    memset(vis,false,sizeof(vis));

    memset(money,INF,sizeof(money));

}

int dij()

{

    dis[0]=0;

    for(int i=1;i<=allnum;i++)

        dis[i]=money[0][i];

    for(int i=1;i<=allnum;i++)

    {

        int minn=INF,x;

        for(int j=1;j<=allnum;j++)

        {

            if(!vis[j]&&dis[j]<=minn)

                minn=dis[x=j];

        }

        vis[x]=true;

        for(int j=1;j<=allnum;j++)

        {

            if(!vis[j]&&dis[j]>dis[x]+money[x][j])

                dis[j]=dis[x]+money[x][j];

        }

    }

    return dis[1];

 

}

 

int main()

{

    while(~scanf("%d%d",&limit,&allnum))

    {

        init();

        for(int i=1;i<=allnum;i++)

        {

            scanf("%d%d%d",&price[i],&level[i],&rep[i]);

            for(int j=0;j<rep[i];j++)

            {

                scanf("%d%d",&num,&charge);

                money[num][i]=charge;

            }

            money[0][i]=price[i];

        }

        int ans=INF;

        for(int i=1;i<=allnum;i++)

        {

            int k=level[i];

            for(int j=1;j<=allnum;j++)

            {

                if(level[j]-k>limit||k>level[j])            //范围是(k-m,k)

                    vis[j]=true;

                else vis[j]=false;

            }

            int now=dij();

            ans=min(now,ans);

        }

        printf("%d\n",ans);

    }

    return 0;

}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值