codeforces 355C - Vasya and Robot

因为在允许的情况下,必然是左右手交替进行,这样不会增加多余的无谓的能量。

然后根据不同的分界点,肯定会产生左手或右手重复使用的情况,这是就要加上Qr/Ql * 次数。

一开始的想法,很直接,枚举每个分界点,计算出总共要用的能量,取最小的那个即是答案:

#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
    int n,l,r,Q_l,Q_r,w[100000+5];
    scanf("%d%d%d%d%d",&n,&l,&r,&Q_l,&Q_r);
    for(int i=1;i<=n;i++) scanf("%d",&w[i]);

    int ans=2147483647,left_enegry_sum,right_enegry_sum;
    for(int m=0;m<=n;m++) //边界在m右边
    {
        left_enegry_sum=0,right_enegry_sum=0;
        for(int i=1;i<=m;i++) left_enegry_sum+=w[i]*l;
        for(int i=n;i>m;i--) right_enegry_sum+=w[i]*r;
        if(m < n-m) //右手拿的东西多
            right_enegry_sum += ( (n-m) - m - 1 ) * Q_r;
        else if(m > n-m) //左手拿的东西多
            left_enegry_sum += ( m - (n-m) - 1 ) * Q_l;
        ans=min(ans , left_enegry_sum + right_enegry_sum);
        //printf("now:\n\tleft_enegry_sum=%d\tright_enegry_sum=%d\tenegry_sum=%d\n",left_enegry_sum,right_enegry_sum,ans);
    }
    printf("%d\n",ans);
}

但是在数据来那个很大的情况下会超时。

所以考虑到我们的枚举分界点方向是从左到右,那么我们不需要每次枚举分界点都O(n)地去计算左右手拿物品的能量

#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
    int n,l,r,Q_l,Q_r,w[100000+5];
    scanf("%d%d%d%d%d",&n,&l,&r,&Q_l,&Q_r);
    for(int i=1;i<=n;i++) scanf("%d",&w[i]); w[0]=0;

    int ans=2147483647,left_energy_sum=0,right_energy_sum=0;
    for(int i=1;i<=n;i++) right_energy_sum+=w[i]*r;
    for(int m=0;m<=n;m++) //边界在m右边
    {
        left_energy_sum+=w[m]*l; //分界点右移一位,left_enrgy_sum增加新增的那一个物品消耗的能量即可
        right_energy_sum-=w[m]*r; //分界点右移一位,right_enrgy_sum减少那一个物品消耗的能量即可
        if(m < n-m) //右手拿的东西多
            ans=min(ans , left_energy_sum + right_energy_sum + ( (n-m) - m - 1 ) * Q_r);
        else if(m > n-m) //左手拿的东西多
            ans=min(ans , left_energy_sum + ( m - (n-m) - 1 ) * Q_l + right_energy_sum);
        else //两只手拿的一样多
            ans=min(ans , left_energy_sum + right_energy_sum);
        //printf("now:\n\tleft_energy_sum=%d\tright_energy_sum=%d\tenergy_sum=%d\n",left_energy_sum,right_energy_sum,ans);
    }
    printf("%d\n",ans);
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值