Bribing Friends

题目

Bessie has N (1≤N≤2000) friends. However, not all friends are created equal! Friend i has a popularity score of Pi (1≤Pi≤2000), and Bessie wants to maximize the sum of the popularity scores of the friends accompanying her. Friend ii is only willing to accompany Bessie if she gives them Ci (1≤Ci≤2000) moonies. They will also offer her a discount of 1 mooney if she gives them Xi(1≤Xi≤2000) ice cream cones. Bessie can get as many whole-number discounts as she wants from a friend, as long as the discounts don't cause the friend to give her mooney.

Bessie has A moonies and B ice cream cones at her disposal (0≤A,B≤2000). Help her determine the maximum sum of the popularity scores she can achieve if she spends her mooney and ice cream cones optimally!

输入

Line 1 contains three numbers N, A, and B, representing the number of friends, the amount of mooney, and the number of ice cream cones Bessie has respectively.

Each of the next N lines contains three numbers, Pi, Ci, and Xi, representing popularity (Pi), mooney needed to bribe friend ii to accompany Bessie (Ci), and ice cream cones needed to receive a discount of 1 mooney from friend i (Xi).

输出

Output the maximum sum of the popularity scores of the friends accompanying Bessie, assuming she spends her moonie and ice cream cones optimally.

样例输入

3 10 8
5 5 4
6 7 3
10 6 3

样例输出

15

题目大意

小B有n个朋友,每个朋友有一个受欢迎度pi。小B想邀请部分朋友和他去看电影,且想要最大化这些朋友的受欢迎程度之和。对于朋友i,只有当小B给他ci元钱,他才会答应去。如果小B BB给他xi
个冰激凌,他还可以给小B 一元的折扣。小B可以从朋友那里得到任意整数数量的折扣,只要不是这些朋友倒贴他。小B 有a 元钱和b个冰激凌,求他在采用最佳策略的情况下,可以达到的最大的受欢迎程度之和。

1<=n<=2000,0<=a,b,<=2000,1<=ci,xi,pi<=2000

题解

首先会想到f[i][j],i表示钱,j表示冰淇淋,这样dp要n^3显然不行;

那么就会想到钱和冰淇淋分开dp,要满足达到最大很显然冰淇淋要用在xi小的人身上,所以我们对数据按照xi的大小升序排序,让[1,k-1]的人用冰淇淋,[k+1,n]的人用钱,k用冰淇淋和钱,这样就只需要n^2了。用f[i][j]标记前i个人用j个冰淇淋的最大值;用 dp[i][j]标记第n个人到第i个人用j个钱的最大价值。

AC代码

#include <bits/stdc++.h>
using namespace std;
class tt
{
public:
    long long p, c, x;
};
tt a[2007];
long long f[2007][2007], dp[2007][2007];
int cmp(tt x, tt y)
{
    return x.x < y.x;
}
void solve()
{
    memset(f, 0, sizeof f);
    memset(dp, 0, sizeof dp);
    int n, m, l;
    cin >> n >> m >> l;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i].p >> a[i].c >> a[i].x;
    }
    sort(a + 1, a + n + 1, cmp);
    for (int i = 1; i <= n; i++)
    {
        long long mm = a[i].c * a[i].x;
        for (int j = 0; j < mm && j <= l; j++)
        {
            f[i][j] = f[i - 1][j];
        }
        for (int j = mm; j <= l; j++)
        {
            f[i][j] = max(f[i - 1][j], f[i - 1][j - mm] + a[i].p);
        }
    }
    for (int i = n; i > 0; i--)
    {
        for (int j = 0; j < a[i].c && j <= m; j++)
        {
            dp[i][j] = dp[i + 1][j];
        }
        for (int j = a[i].c; j <= m; j++)
        {
            dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - a[i].c] + a[i].p);
        }
    }
    long long maxx = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= a[i].c && j <= m; j++)
        {
            if ((a[i].c - j) * a[i].x > l) //
            {
                maxx = max(maxx, f[i - 1][l] + dp[i + 1][m]);
            }
            else
            {
                maxx = max(maxx, f[i - 1][l - (a[i].c - j) * a[i].x] + dp[i + 1][m - j] + a[i].p);
            }
        }
    }
    cout << maxx << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值