C语言入门算法——采药(了解动态规划)

题目描述:

辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”

如果你是辰辰,你能完成这个任务吗?

输入格式

第一行有 2个整数 T(1≤T≤1000)和 M1≤M≤100),用一个空格隔开,T 代表总共能够用来采药的时间,M 代表山洞里的草药的数目。

接下来的 M 行每行包括两个在 1到 100 之间(包括 1 和 100)的整数,分别表示采摘某株草药的时间和这株草药的价值。

输出格式

输出在规定的时间内可以采到的草药的最大总价值。

输入输出样例

输入 #1

70 3
71 100
69 1
1 2

输出 #1

3

说明/提示

【数据范围】

  • 对于 30%30% 的数据,M≤10;
  • 对于全部的数据,M≤100。

题目来源:

P1048 [NOIP2005 普及组] 采药

思路及部分代码:

1. 分析

        我在最初想直接暴力解决这类问题,当然超时了。便对动态规划进行了初步的了解。

        C语言入门算法——爬楼梯(了解动态规划)

        在本题中, 先将一个药品的所需时间保存下来,

        假设:    能采药草数:mi

                       能采药草的时间: ti

        dp [ mi ] [ ti ] = max (新药草价值 + dp [ mi - 1] [ 采新药草剩余时间 ] , dp [ mi - 1][ ti ] ); 

2. 求最大值函数


int max(int a, int b){
    return (a>b)?a:b;
}

3. 动态规划


int dp_max(int t, int m){
    dp[0][0] = 0;
    for(int mi = 0; mi < m; mi++){  //药品数
        for(int ti = 1; ti <= t ; ti++){    //mi个药品,不同时间能采的最大值
            if(mi == 0){
                if(ti >= drug_all[mi][0]){
                    dp[mi][ti] = max(drug_all[mi][1], dp[mi][ti - 1]); //将药品为1时间所能保存的药品最大价格
                }
            }
            else{//其余情况
                    if(ti >= drug_all[mi][0]){  //能采最新药草
                        int ti_i = ti - drug_all[mi][0];    //采新药的最新时间

                        //                  新药价值      剩余时间的最大价值  不买最大新药价值 
                        dp[mi][ti] = max(drug_all[mi][1] + dp[mi-1][ti_i], dp[mi - 1][ti]); 
                        //printf("%d ", dp[mi][ti]);
                    }
                    else{
                        dp[mi][ti] = dp[mi - 1][ti];
                    }
            }
            //printf("%4d ", dp[mi][ti]);
        }
        //printf("\r\n");
    }

    return dp[m-1][t];
}

总代码:

#include <stdio.h>

int drug_all[110][2];   //保存药的数据
int dp[1010][1010];  //动态规划数组


int max(int a, int b){
    return (a>b)?a:b;
}

int dp_max(int t, int m){
    dp[0][0] = 0;
    for(int mi = 0; mi < m; mi++){  //药品数
        for(int ti = 1; ti <= t ; ti++){    //mi个药品,不同时间能采的最大值
            if(mi == 0){
                if(ti >= drug_all[mi][0]){
                    dp[mi][ti] = max(drug_all[mi][1], dp[mi][ti - 1]); //将药品为1时间所能保存的药品最大价格
                }
            }
            else{//其余情况
                    if(ti >= drug_all[mi][0]){  //能采最新药草
                        int ti_i = ti - drug_all[mi][0];    //采新药的最新时间

                        //                  新药价值      剩余时间的最大价值  不买最大新药价值 
                        dp[mi][ti] = max(drug_all[mi][1] + dp[mi-1][ti_i], dp[mi - 1][ti]); 
                        //printf("%d ", dp[mi][ti]);
                    }
                    else{
                        dp[mi][ti] = dp[mi - 1][ti];
                    }
            }
            //printf("%4d ", dp[mi][ti]);
        }
        //printf("\r\n");
    }

    return dp[m-1][t];
}


int main(){
    int T,M;
    scanf("%d %d",&T, &M);

    //接收数据
    for(int i = 0; i < M; i++){
        scanf("%d %d",&drug_all[i][0], &drug_all[i][1]);
    }
    printf("%d\r\n", dp_max(T,M));

    return 0;
}

总结:

        这段代码实现了一个动态规划算法,用于解决背包问题的变种。它通过填充一个二维数组 dp 来记录在不同的时间和不同的药品数量下的最大药品价格总和。但对动态规划了解还较为模糊,还需练习。

不足之处:

  1. 注释: 虽然代码中有一些注释,但是有些地方的注释并不够清晰,建议增加更多的注释来解释代码的逻辑和关键步骤,使得代码更易读。
  2. 函数封装: 目前 dp_max 函数和 main 函数耦合度较高,建议将动态规划逻辑封装成一个独立的函数,以提高代码的可读性和可维护性。
  3. 错误处理: 目前的代码没有对输入进行错误处理,比如输入的时间或药品数量可能为负数,这种情况下代码会出现问题。建议添加输入验证,对不合理的输入进行处理和提示。

改进建议:

  1. 函数封装: 将动态规划逻辑封装成一个独立的函数,并将其与 main 函数分离,以提高代码的模块化和可维护性。
  2. 错误处理: 在 main 函数中添加输入验证,对不合理的输入进行处理和提示,以提高代码的健壮性。
  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0X78

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值