A - 高数Umaru系列(9)——哈士奇

    科技2025-08-29  10

    A - 高数Umaru系列(9)——哈士奇

    Description

    由于高数巨养的喵星人太傲娇了,要天天吃新鲜猫粮而且还经常欺负高数巨,所以高数巨决定买几条哈士奇尝尝鲜。这天高数巨来到了二手狗市场买哈士奇,高数巨看完了所有的哈士奇,记下了每条哈士奇的价格,并根据对它们的好感程度给它们每只都赋予了一个萌值。高数现在手里有X元,她想通过购买若干条哈士奇来获得尽可能多的萌值。现在给定高数巨手里的钱X以及N条哈士奇的价格和萌值,求高数巨最多可获得多少萌值

    Input

     多组输入。

    对于每组输入,第一行有两个整数N,X(1 < = N < = 100,1 < = X < = 1000),分别表示哈士奇的数量和高数巨的钱数

    接下来的N行每行有两个整数Pi,Mi(1 < = Pi,Mi < = 100),分别表示第i条哈士奇的价格和萌值

    Output

    对于每组数据,输出一个整数,表示高数巨最多可以获得的萌值,每组输出占一行

    Sample

    Input 

    2 100 50 20 60 40 3 100 20 55 20 35 90 95 1 10 20 50

    Output 

    40 95 0

    Hint

    动态规划典型题目,相当于背包问题。

    就本题而言,我们需要做的是建立一个dp二维数组,用来存放每一次输入价格和萌值之后进行比对的萌值,直到比对完最后一组,输出dp[n][x]即可。

    核心代码:

    for(int j=1;j<=x;j++)              {                  dp[i][j]=(i==1?0:dp[i-1][j]);                  if(j>=p)                  {                      dp[i][j]=max(dp[i-1][j],dp[i-1][j-p]+m);                  }              }

    拿题目中所给的数据进行举例促进理解。Sample Input 3 100,之后就会建立一个三行一百列的dp数组dp[3][100](初值为0);

    之后input 20 55,由于这是第一个输入的数据组,所以i==1,所以从j=1,到j=20,dp[1][1~19]的值都为0,而当j遍历到20时,dp[1][20]=max(dp[0][20],dp[0][0]+55),显然dp[1][20~100]都将等于55.

    接着input 20 35,第二个输入的数据组,i==2,此时,i!=1,所以dp[2][1~19]的值都为dp[1][1~19]=0,当j遍历到20时,

    dp[2][20]=max(dp[1][20],dp[1][0]+35)=55,dp[2][40]=max(dp[1][40],dp[1][20]+35)=55+35=90;此处取的是两个极限值,显然j-p,一个是j-p=0,j=20,和j-p=20,j=40每一组的极限值取决于上一次所输入的价格。所以,dp[2][20~39]=55,dp[2][40~100]=90。

    到这一步,可以看出前两组数据所输入的萌值在两次的价格相加即20+20=40处开始进行类累加。

    最后input 90 95,i==3,i!=1,dp[3][1~19]=dp[2][1~19]=0.dp[3][20~39]=55,dp[3][40~89]=90.(此处就是

    dp[i][j]=(i==1?0:dp[i-1][j]语句的体现,作用是继承上次数据的值);再继续向后遍历,同上遍历,p=90,当j>=p时,即dp[3][90~100]=max(dp[2][90~100],dp[2][0~10]+m)=max(90,95)=95;

    至此完成背包问题的求解,就是不断选取并继承上一次的萌值进行比较,进行分阶段的管理,动归的思想其实就是不断继承,不断地将新的一组数据与上一组数据比较,(在不超过界值的情况下)

    AC代码:

    #include<bits/stdc++.h> using namespace std; int max(int a,int b)//比较函数; { return a>b?a:b;//三目运算 } int main() { int n,x,p,m; while(cin>>n>>x){ int dp[110][1009]={0};//dp数组初始化 for(int i=1;i<=n;i++) { cin>>p>>m; for(int j=1;j<=x;j++)//j从1到所给的金额开始遍历 { dp[i][j]=(i==1?0:dp[i-1][j]);//继承上一行中的数据,进行数据的迁移 if(j>=p) { dp[i][j]=max(dp[i-1][j],dp[i-1][j-p]+m);//见上面解析 } } } cout<<dp[n][x]<<endl; } return 0; }

    ================================================================================================

    纯手打,理解了给个赞吧

    Processed: 0.012, SQL: 8