CodeForces - 89A - Robbery

题目链接http://codeforces.com/problemset/problem/89/A

题意:有n堆钻石,编号为1~n,钻石个数为a1~an,现要从中拿走一些钻石,但是有警报系统规则入下:警报系统每一分钟检查一次,每次检查结果是紧挨着的的两堆钻石之和,那么n堆钻石可得结果集res12,res23,res34...res(n-1)(n),这里要保证拿钻石过程不会使得前后两次检查所得结果集不同,那么又有m限制每分钟操作次数不超过m次,这里操作分为3种:1.将一个钻石从一堆移动到另一堆;2.将钻石从某堆移动到口袋;3.将钻石从口袋移动到某一堆。总共有时间k分钟问最多能拿多少钻石。

解析:发现只有在钻石堆数为奇数时,执行如下步骤能拿走1颗钻石且警报不会触发:

1.选择某序号为奇数的钻石堆,拿走其中一个钻石

2.将其左侧的2*i堆钻石分组:从左端开始两个一组,对于所有组从左边堆拿1个钻石放到右边堆

3.将其右侧的2*j堆钻石分组:从左端开始两个一组,对于所有组从左边堆拿1个钻石放到右边堆


对于正常情况下,由于执行一次拿步骤需要(n/2)+1次操作,对于

①.m<(n/2+1)时,一颗也没法拿走;

②.m>=(n/2+1),每分钟拿走m/(n/2+1)个,直到拿了k分钟或者在过程中某奇数序号堆钻石数为0时也不能再拿了;

注意:只有一堆时(n=1)警报是不管用的,所以每分钟都可以拿m颗钻石直到拿光或者时间用光

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=1e4+5;
ll n,m,k,a[M];
int main()
{
    scanf("%lld%lld%lld",&n,&m,&k);
    ll minV=0x7fffffff;
    for(ll i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        if(i&1)
            minV=min(minV,a[i]);
    }
    if(n==1)
    {
        printf("%lld\n",min(a[1],k*m));
    }else if((n&1)==0)
    {
        printf("0\n");
    }else
    {
        ll tmp=(n>>1)+1;//拿一颗钻石用几次操作
        if(m<tmp)
        {
            printf("0\n");
        }else{
            printf("%lld\n",min(minV,k*(m/tmp)));
        }
    }
    return 0;
}

阅读更多
版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/sdau20163942/article/details/80343925
文章标签: Codeforces
个人分类: Codeforces
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭