Codeforces Round #775 (Div. 2)(含B题的贪心证明)

A. Game

You are playing a very popular computer game. The next level consists of n consecutive locations, numbered from 1 to n, each of them containing either land or water. It is known that the first and last locations contain land, and for completing the level you have to move from the first location to the last. Also, if you become inside a location with water, you will die, so you can only move between locations with land.

You can jump between adjacent locations for free, as well as no more than once jump from any location with land i to any location with land i+x, spending x coins (x≥0).

Your task is to spend the minimum possible number of coins to move from the first location to the last one.

Note that this is always possible since both the first and last locations are the land locations.

Input
There are several test cases in the input data. The first line contains a single integer t (1≤t≤100) — the number of test cases. This is followed by the test cases description.

The first line of each test case contains one integer n (2≤n≤100) — the number of locations.

The second line of the test case contains a sequence of integers a1,a2,…,an (0≤ai≤1), where ai=1 means that the i-th location is the location with land, and ai=0 means that the i-th location is the location with water. It is guaranteed that a1=1 and an=1.

Output
For each test case print a single integer — the answer to the problem.

这道题用双指针就可以求出0~0的边界,注意特判

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N =102;
int a[N];
int cnt;
 
int main()
{
    int T;
    cin>>T;
    int res=0;
    while(T--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i];
        int l=1,r=n;
        while((l<=n)&&(a[l]==1))l++;
        while((r>=1)&&(a[r]==1))r--;
        if(l>r)puts("0");
        else cout<<r-l+2<<endl;
    }
    
    
    return 0;
}

B. Game of Ball Passing

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Daniel is watching a football team playing a game during their training session. They want to improve their passing skills during that session.

The game involves n players, making multiple passes towards each other. Unfortunately, since the balls were moving too fast, after the session Daniel is unable to know how many balls were involved during the game. The only thing he knows is the number of passes delivered by each player during all the session.

Find the minimum possible amount of balls that were involved in the game.

Input
There are several test cases in the input data. The first line contains a single integer t (1≤t≤5⋅104) — the number of test cases. This is followed by the test cases description.

The first line of each test case contains one integer n (2≤n≤105) — the number of players.

The second line of the test case contains a sequence of integers a1,a2,…,an (0≤ai≤109), where ai is the number of passes delivered by the i-th player.

It is guaranteed that the sum of n over all test cases doesn’t exceed 105.

Output
For each test case print a single integer — the answer to the problem.

题目分析:

如果只有两个人,且两人的传球次数只有一次,那么第一个拿球的人a先传给b,b再传回a,那么两人的次数都被消耗,但如果出现人c,假设a还有传球次数,那么a就可以传给c,且c不增加传球次数,a可以多消耗一次。
那么,不妨让传球次数最多的人先拿球,那么用最大的一项去消耗其他比他次数少的人,这样能贪心(局部最优解)

贪心提出假设:如果max⋅2 ≤ sum,我们总是可以证明我们只能使用一个球。 对于其他情况,球的数量就是2⋅max−sum。

证明结论:为了方便证明,不妨将a1~an从小到大排序,最大的数为an,利用反证法:如果2*max>sum的话就能够让其他数字内部消化(即能够互相传球达到消消乐的效果)。又因为max=an,同时减去an,得max>sum[n-1] 那么利用之前1对1 的结论总有一个点会大于等于1,假设不成立(注意,如果有一个点为1,那么还是可以传给其它人)因此逆否命题也可以求出。

AC代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N =1e5+3;
typedef long long LL;
int a[N];
int cnt;

LL sum;
int main()
{
    int T;
    cin>>T;
    int res=0;
    while(T--)
    {
        int n;
        cin>>n;
        sum = 0;
        int maxn=0;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
            maxn = max(maxn,a[i]);
            sum +=a[i];
        }

        if(sum == 0)cout<<0<<endl;		//特判一下
        else
        {
            if(2 * maxn<=sum)cout<<1<<endl;
            else
            {
                cout<<2*maxn - sum<<endl;
            }
        }
        
        
    }
    
    
    return 0;
}

未完待续

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值