CODE[VS]1025 选菜

博客详细介绍了如何解决CODEVS上的1025选菜问题,通过将价格和钱数乘以10转换为整型避免浮点运算误差,排除必须菜品和美味值为0的选项,然后利用动态规划算法求得最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目: http://codevs.cn/problem/1025/
思路:将价格和钱数浮点型值乘以10后,转换为整型。然后根据数据,将必须菜和美味值为0的菜从所有菜式中剔除。建立一个可选菜式队列,然后使用动态规划算法求解。
题解:

/* 1025 选菜 */ 
#include <stdio.h>

#define MAXN 101        /* 最大菜式数 */ 
#define MAXM 1001       /* 最大钱数 */ 

/* 菜式清单 */
struct _food{
    int d;          /* 美味值  */ 
    int r;          /* 必选标记 */ 
    int p;          /* 价格 */ 
}food[MAXN]; 

int n, k, m;                                    /* 菜式,必选菜数, 钱数 */
int id[MAXN], delicious[MAXN], prices[MAXN];    /* 价目编号,美味值, 价目表 */ 
int reqd, required[MAXN];                       /* 必选美味值,必选菜单 */ 
int queue[MAXN], count;                         /* 可选菜式队列,可选菜计数 */

int maxd[MAXM][MAXN];   /* 最大美味值表 */ 

/* 01背包算法求解最大美味值表 */ 
void get_maxd(){
    int ic, jr;     /* 美味值表行列索引值 */ 
    int f, p;       /* 菜式编号,价格 */ 
    /* 初始化第一行 */
    f = queue[0];
    p = food[f].p;
    for(jr = 0; jr <= m; jr++){
        /* 菜式价格低于钱数,美味值等于当前菜式美味,否则为0 */ 
        if(p <= jr){
            maxd[jr][0] = food[f].d;
        }
        else{
            maxd[jr][0] = 0;
        }
    }
    /* 获取最大美味值表 */
    for(ic = 1; ic < count; ic++){
        f = queue[ic];
        p = food[f].p;
        for(jr = 0; jr <= m; jr++){
            /* 菜式价格高于总钱数,美味值不变 */ 
            if(p > jr){
                maxd[jr][ic] = maxd[jr][ic - 1];
            }
            /* 否则美味值等于maxd[jr][ic-1] 和maxd[jr-p][ic-1]+food[f].d的最大值 */ 
            else{
                if(maxd[jr][ic - 1] > maxd[jr - p][ic - 1] + food[f].d){
                    maxd[jr][ic] = maxd[jr][ic - 1];
                }
                else{
                    maxd[jr][ic] = maxd[jr - p][ic - 1] + food[f].d;
                }
            }
        }
    } 

    /* 测试 - 打印美味值表 */
    /* 
    for(ic = 0; ic < count; ic++){
        for(jr = 0; jr <= m; jr++){
            printf("%d ", maxd[jr][ic]);
        }
        printf("\n");
    } 
    */ 
}

/* 计算可选菜式队列 */
void queue_food(){
    int i, j;       /* 索引值 */
    int f, d, p;    /* 编号,美味,价格 */ 
    int max;        /* 最大编号值 */ 
    max = 0;
    /* 遍历数据,将菜式保存到结构体中 */
    for(i = 1; i <= n; i++){
        f = id[i];
        food[f].d = delicious[i];
        food[f].p = prices[i];
        food[f].r = 0;
        if(f > max){
            max = f;
        }
    } 
    /* 遍历必选菜单,更新美味值和钱数 */
    reqd = 0; 
    for(i = 1; i <= k; i++){
        f = required[i];
        food[f].r = 1;
        reqd = reqd + food[f].d;
        m = m - food[f].p;
    } 
    /* 遍历菜单,将非必选且美味值不为0的菜式入队 */
    count = 0; 
    for(j = 1; j <= max; j++){
        if(0 == food[j].r && food[j].d > 0){
            queue[count] = j;
            food[j].r = 1;
            count++;
        } 
    }
}           

/* 主函数入口 */ 
int main(int argc, char *argv[]) {
    int i;  /* 索引值 */ 
    float tmp;
    /* 打开数据文件 */ 
    FILE *fp;
    if(NULL == (fp = fopen("data.txt","r"))){
        return 0;
    }
    /* 获取菜式,必选菜数,钱数 */ 
    fscanf(fp, "%d %d %f", &n, &k, &tmp);
    m = tmp * 10;
    /* 获取价目表 */ 
    for(i = 1; i <= n; i++){
        fscanf(fp, "%f", &tmp);
        prices[i] = tmp * 10;
    }
    /* 获取美味值 */
    for(i = 1; i <= n; i++){
        fscanf(fp, "%d", &delicious[i]);
    } 
    /* 获取编号 */
    for(i = 1; i <= n; i++){
        fscanf(fp, "%d", &id[i]);
    } 
    /* 获取必选菜编号 */
    for(i = 1; i <= k; i++){
        fscanf(fp, "%d", &required[i]);
    }  
    /* 获取菜单队列 */ 
    queue_food();
    /* 计算最大美味值表 */ 
    get_maxd();
    /* 输出结果 */ 
    printf("%d", reqd + maxd[m][count - 1]); 
    /* 关闭数据文件 */ 
    fclose(fp);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值