洛谷P1509 找啊找啊找G——教你如何花尽量少的时间泡更多的妹子

一、题目描述

https://www.luogu.com.cn/problem/P1509
感觉题目挺好意思的,泡妹子需要花费 钱和人品还有时间,所以你需要在钱和人品一定的情况下,尽可能花费时间最少,泡到妹子数量最多。

二、思想

感觉题目不是很难,背包问题,很好想。跟以往做的背包问题就是多了两个限制条件 钱和人品。
以往的背包问题一个限制条件我们使用二维数组,那么这里需要使用三维数组,很复杂,所以我们将以往的背包问题压缩成一维数组,那么这里就需要二维数组了。
压缩成二维数组 dp[j][k]:花费的钱为j,人品为k时,所能泡到的妹子个数。
我们只需要循环n个妹子 每个妹子每次计算的dp[j][k] ,根据条件覆盖前一个妹子计算的dp[j][k]
三层for循环:第一层 妹子人数;第二层 花费的钱;第三层 花费的人品
第三层for循环里就是dp方程;
如果花更多的钱和人品泡到了更多的妹子,那么就前一个覆盖dp[j][k]

   dp[j][k]=dp[j-gf[i].rmb][k-gf[i].rp]+1

每个妹子的价值都为1。
如果花更多的钱和人品 泡到妹子的数量是相同的 那么我们选花时间少的。

t[j][k]=min(t[j-gf[i].rmb][k-gf[i].rp]+gf[i].time,t[j][k]

这里只有这两种情况, 没有可能花更多的钱和人品,泡到妹子个数反而少的情况
在第二、三层循环种 我们一定要逆序因为我们压缩了数组。
下面以 二维压一维(三维压二维类似) 为例:
如果我们没有压缩数组采用一维数组,那么我们更新每一行的值需要上一行没更新的值。
压缩后,采用一维数组,我们如果采用从前向后更新,那么前面的数值都改变了,后面的值要依据前面的值进行改变,而前面的值已经不是上一行的值了(在二维中)。
所以我们采用从后向前更新,后面值的更新时前面的值一定是上一行的。
例:以测试案例为例

4
1 2 5
2 1 6
2 2 2
2 2 3
5 5

在第一个妹子时,dp[1][2]=1 ,dp[1-5] [2-5]=1
第二个妹子时 ,
如果采用从前向后更新: dp[3][3]=dp[3-2][3-1]+1=2,
dp[5][5]=dp[5-2][5-2]+1=dp[3][3]+1=3 泡第二个妹子时,能泡到最大个数就是3了。
如果从后向前 dp[5][5]=dp[3][3]+1=1+1=2。
所以……懂了吧!

三、代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

struct Gfd{
    int time;
    int rmb;
    int rp;

    void set_Gfd(int rmb0,int rp0,int time0){
        time=time0;
        rmb=rmb0;
        rp=rp0;
    }
}gf[15];
int main(){
    // dp[j][k] 泡妹子 身上还有的钱j 和 人品k 能泡到的妹子个数
    int dp[105][105]={0},t[105][105]={0};
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int rmb,rp,time;
        scanf("%d%d%d",&rmb,&rp,&time);
        gf[i].set_Gfd(rmb,rp,time);
    }
    int m,r;
    scanf("%d%d",&m,&r);
    for(int i=1;i<=n;i++){
        //注意 一定要从后往前推
       //泡妹子的前提是有钱和有人品,否则白搭
        for(int j=m;j>=gf[i].rmb;j--){
            for(int k=r;k>=gf[i].rp;k--){
                //花更多的钱和人品泡到了更多的妹子
                if(dp[j-gf[i].rmb][k-gf[i].rp]+1>dp[j][k]){
                    dp[j][k]=dp[j-gf[i].rmb][k-gf[i].rp]+1;
                    //相应的花了时间
                    t[j][k]=t[j-gf[i].rmb][k-gf[i].rp]+gf[i].time;
                }
                //如何拿更多的钱和人品 泡到妹子的数量是相同的 那么我们选花时间少的。
                else if(dp[j-gf[i].rmb][k-gf[i].rp]+1==dp[j][k]){
                    t[j][k]=min(t[j-gf[i].rmb][k-gf[i].rp]+gf[i].time,t[j][k]);
                }
            }
        }
    }
    printf("%d",t[m][r]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mae_strive

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

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

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

打赏作者

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

抵扣说明:

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

余额充值