HRBU_20211013训练

目录

A - Drinks Choosing

题意:

做法:

B - Sport Mafia

题意:

做法:

C - Basketball Exercise

题意:

做法:


题意:

n个人每个人都有自己喜欢喝的avechorka口味,现在给你⌈n/2⌉(向上取整)箱vechorka,每箱有两瓶,问最多能有多少个人能拿到自己喜欢的口味。

做法:

我们首先记录每个口味有多少个人喜欢,然后要想拿到自己喜欢的口味最大那么一定要优先考虑能凑偶数的,把偶数考虑完后剩余的口味一定都是11,就不管怎么分都只能满足一半的人。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,k;
    int a[N];
    memset(a,0,sizeof(a));
    cin>>n>>k;
    int re = (n / 2) + (n & 1);
    int ans = 0;
    for(int i = 1; i <= n; i++)
    {
        int num;
        cin>>num;
        a[num]++;
        if(a[num] == 2 && re)
        {
            ans += 2;
            re--;
            a[num] = 0;
        }
    }
    for(int i = 1; i <= k; i++)
    {
        if(!re)
            break;
        if(a[i])
        {
            re--;
            ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}

B - Sport Mafia

题意:

你有一个盒子,你可以进行两种操作,首先你可以往盒子里加糖果,每一次添加的糖果都得比前一次添加的糖果多1;或者你可以从盒子里吃掉1颗糖果。你一共要进行n次操作,然后你得保证n次操作后盒子里只有k颗糖果,问你最后吃了多少糖果?

做法:

首先我们每次添加糖果的操作是每次+1,也就相当于这是一个等差序列,那么我们进行一个等差序列求和:假设一共操作了a次添加糖果,那么一共添加了((a+1)*a)/2颗糖果;然后假设我们一共吃了b颗糖果,那么满足a+b=n&&((a+1)*a)/2-b=k,接着我们将两个式子进行联立,得到一个结果式:a*(a+3)=2*(n+k),接着给这个变成不等式就得到了(a*(a+3))/2-n>=k,这就可以运用二分思想进行答案二分然后判断即可,注意会卡int,判断的时候得改成long long,或者直接开long long

#include<bits/stdc++.h>
//#define int long long
typedef long long ll;
using namespace std;
const int mod=1e9+7;
const int maxn=1e5+10;
ll n,k;
bool judge(ll a)
{
    return (a*(a+3))/2-n>=k;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    while(cin>>n>>k)
    {
        ll l=0,r=n,mid,ans=0;
        while(r>=l)
        {
            mid=(l+r)/2;
            if(judge(mid))
            {
                ans=mid;
                r=mid-1;
            }
            else
                l=mid+1;
        }
        cout<<n-ans<<endl;
    }
    return 0;
}

C - Basketball Exercise

题意:

你是一个篮球教练,你拥有2*n个篮球队员,你需要从这2*n个队员中挑选出随机数量的球员,要求满足他们的身高和最大,挑选过程中你不可以同时挑选同一列中的两个相邻的球员,并且挑选顺序只能是从左往右去挑选

做法:

一个大概能看的出来的dp题(别问!问就是事后补题,你刚就是你对!)两列球员,那么设置dp数组时就得设置dp[n][3]了,为啥是3组呢?代表三种情况:1、dp[i][0]表示从第一列中当编号为i时最高的身高数。2、dp[i][1]表示从第二列中当编号为i时最高的身高数。3、dp[i][2]表示两列都不选择时当编号为i时最高的身高数。

状态转移方程为:

dp[i][0]=max(dp[i−1][1],dp[i−1][2])+a[i] 

 dp[i][1] = max(dp[i-1][0], dp[i-1][2]) + b[i];

dp[i][2]=max(dp[i−1][0],dp[i−1][1],dp[i−1][2])

 最后对于dp[n][0],[1],[2]取最大即可!

#include<bits/stdc++.h>
//#define int long long
typedef long long ll;
using namespace std;
const int mod=1e9+7;
const int maxn=1e5+10;
ll n,k,a[maxn],b[maxn];
ll dp[maxn][3];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<=n;i++)
            cin>>b[i];
        for(int i=1;i<=n;i++)
        {
            dp[i][0]=max(dp[i-1][1],dp[i-1][2])+a[i];
            dp[i][1]=max(dp[i-1][0],dp[i-1][2])+b[i];
            dp[i][2]=max(dp[i-1][0],max(dp[i-1][1],dp[i-1][2]));
        }
        cout<<max(dp[n][0],max(dp[n][1],dp[n][2]))<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值