Hoofball [codeforces] (思维题)

原题传送门


题面:

Hoofball

                                 time limit per test : 5 seconds
                              memory limit per test : 512 megabytes
                                     input : standard input
                                    output : standard output

Problem Description

In preparation for the upcoming hoofball tournament, Farmer John is drilling his N cows (conveniently numbered 1…N, where 1≤N≤100) in passing the ball. The cows are all standing along a very long line on one side of the barn, with cow i standing xi units away from the barn (1≤xi≤1000). Each cow is standing at a distinct location.

At the beginning of the drill, Farmer John will pass several balls to different cows. When cow i receives a ball, either from Farmer John or from another cow, she will pass the ball to the cow nearest her (and if multiple cows are the same distance from her, she will pass the ball to the cow farthest to the left among these). So that all cows get at least a little bit of practice passing, Farmer John wants to make sure that every cow will hold a ball at least once. Help him figure out the minimum number of balls he needs to distribute initially to ensure this can happen, assuming he hands the balls to an appropriate initial set of cows.

Input

The first line of input contains N. The second line contains N space-separated integers, where the ith integer is xi.

Ouput

Please output the minimum number of balls Farmer John must initially pass to the cows, so that every cow can hold a ball at least once.

Sample Input

5
7 1 3 11 4

Sample Output

2

题意描述

牛会把球踢给离它最近的牛,若两边都离它最近,他就会把球踢给左边的牛.John想用最少数量的球让全部牛都能拿到一次球.

题目分析

动态规划.枚举每一头牛作为开球牛Cow0,找到球转移的区间,有 dp[i] = min( dp[i] , dp[cow-1]+1 ).而作为球转移的区间结尾特征是已经踢过球的牛会再次作为下一头踢球的牛.所以可以用一个vis数组记录哪些牛在Cow0作为开球牛的踢球区间内已经踢过球.

具体代码

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int cow[105];
bool vis[105];
bool fx[105];
int dp[105];
int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &cow[i]);
    }
    sort(cow+1, cow+n+1);
    fx[1] = true, fx[n] = false;//true代表向右踢,false代表向左  第一头牛必定向右,最后一头必定向左
    for(int i = 2; i <= n-1; i++)
    {
        if(cow[i]-cow[i-1] <= cow[i+1]-cow[i])
        {
            fx[i] = false;
        }
        else
        {
            fx[i] = true;
        }
    }
    memset(dp, inf, sizeof(dp));
    dp[0] = 0;
    for(int i = 1; i <= n; i++)
    {
        memset(vis, false, sizeof(vis));//重置vis,代表所有牛都未访问
        vis[i] = true;
        int maxx = i;
        int minx = i;
        int nxt = fx[i] ? i+1 : i-1;
        while(!vis[nxt])//当下一头牛未访问时继续,若下一头牛已被访问则说明球踢回来了
        {
            vis[nxt] = true;
            maxx = max(maxx , nxt);
            minx = min(minx , nxt);
            nxt = fx[nxt] ? nxt+1 : nxt-1;
        }
        if(minx != i)
        {
            for(int j = minx; j <= i; j++)
            {
                dp[j] = min(dp[j] , dp[minx-1]+1);
            }
        }
        else
        {
            for(int j = i; j<= maxx; j++)
            {
                dp[j] = min(dp[j] , dp[i-1]+1);
            }
        }
    }
    printf("%d\n", dp[n]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43726593/article/details/87926728