codevs 1025 选菜

1025 选菜

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
题目描述 Description

       在小松宿舍楼下的不远处,有PK大学最不错的一个食堂——The Farmer’s Canteen(NM食堂)。由于该食堂的菜都很不错,价格也公道,所以很多人都喜欢来这边吃饭。The Farmer’s Canteen的点菜方式如同在超市自选商品一样,人们从一个指定的路口进去,再从一个指定的路口出来并付款。由于来这里就餐的人数比较多,所以人们自觉地在进入口的时候就排成一个长队,沿着长长的摆放着各式各样佳肴的桌子进行选菜。

       小松发现,这种选菜方式意味着,他不能在选菜的时候离开队伍去拿一些他已经看过了的菜或者没有看过的菜,因为插队是不礼貌的,也是被BS的。

       每个菜有一个价值,而小松也自己给每个菜定了一个在他看来的美味价值,例如红烧小黄鱼在小松看来是美味价值很高的,而花菜在小松眼里则是美味价值极低的菜肴。而有一些菜是营养价值极其高的菜(例如米饭),所以无论它的美味价值是多少,小松都会选择1份。现在小松带了X元钱来食堂就餐,他想知道,在不欠帐的情况下,他选菜的美味价值总合最大是多少。

输入描述 Input Description

       请从输入文件farmer.in中读入相关数据。输入的第一行包括两个个整数n(1≤n100),k(0k实际菜的种类)和一个实数X(0≤X100),表示有n个菜式,有k种菜是必选的,小松带来了X元钱(精确到“角”)。接下来的1行包含n个实数,表示菜桌上从入口到出口的所有菜的价格(0价格10,单位“元”,精确到“角”);再接下来的1行包含n个整数,表示菜桌上从入口到出口的所有菜的美味价值(0美味价值100);再接下来一行包含n个整数,表示菜桌上从入口到出口的所有菜的种类编号(1种类编号100)。最后一行包含k个整数分别表示必选菜的种类编号。要注意的是,同一种编号的菜可以出现多次,但是他们的价格和美味价值都是一样的。对于同一种菜(无论是不是必选菜),小松最多只会选择1份(买两份红烧豆腐多没意思啊)。另外,必选菜的价格之和一定不超过X

输出描述 Output Description

       请将结果输出到输出文件farmer.out中。输出包含一个整数,表示小松能选到的菜的美味价值总和最大是多少。

       注:你可以假设数据中不会出现小松带的钱不够买必买菜的情况。

样例输入 Sample Input

7 1 5.0

4 1 3 0.9 2 0.5 0.9

7 3 5 2 5 0 2

6 3 5 2 4 1 2

2

样例输出 Sample Output

10

数据范围及提示 Data Size & Hint
 

分类标签 Tags 点此展开 

【思路】
01背包
没有想到将有小数的价钱*10 标记每个菜有没有选过
【代码】
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct nn//结构体 价钱 编号 美味价值 
{
    int pri,id,nutri;
}food[1001];
int b[1001];
int f[1001];
int main()
{
    int n,k;
    double xx;//拥有的钱 方便处理*10-----------------*****(没有想到) 
    scanf("%d%d%lf",&n,&k,&xx);
    int x=xx*10;
    for(int i=1;i<=n;i++)
    {
        double yuan;
        scanf("%lf",&yuan);
        food[i].pri=int(yuan*10);//每个菜的价钱的也乘以10 
    }
    for(int i=1;i<=n;i++)
    scanf("%d",&food[i].nutri);//营养 
    for(int i=1;i<=n;i++)
    scanf("%d",&food[i].id);//编号 
    for(int i=1;i<=k;i++)
    scanf("%d",&b[i]);.//必选 
    for(int i=1;i<=n;i++)//先把相同的编号只留下一个 重复的设为零 因为一种菜只能选择一份 
    {
        for(int j=i+1;j<=n;j++)
        {
            if(food[i].id==food[j].id)
            food[j].id=0;
        }
    }
    int all=0;//记录必选菜能获得的总价值 
    for(int i=1;i<=k;i++)
    for(int j=1;j<=n;j++)
    {
        if(food[j].id==b[i])//这个菜是我必须要选择的菜 
        {
            x-=food[j].pri;//
            all+=food[j].nutri;//累计价值 
            food[j].id=0;//买过之后编号变成0 表示应将买过 
        }
    }
    for(int i=1;i<=n;i++)//背包套路 
    {
        if(food[i].id)
        for(int j=x;j>=food[i].pri;j--)
        {
            f[j]=max(f[j],f[j-food[i].pri]+food[i].nutri);
        }
    }
    printf("%d",f[x]+all);
    return 0;
}
原文地址:https://www.cnblogs.com/zzyh/p/6752683.html