Greedy:The Water Bowls(POJ 3185)

                

                  水池

  题目大意:给定一个20的数组,全都是0和1,可以翻一个数改变成另一个数(0或者1),但是其左右两边的数都会跟着变为原来的相反数,问你怎么用最小的操作数使全部数变成0

  这一题的:满足

    1:翻转次序不改变结果

    2.  从特定次序翻转以后左侧的元素不会再改变

    其实就是3276的变形,只是他这次固定变三个数,而且是一前一后,我们把方向dir的查看往前挪一个数就好了,但是这样我们就不能知道第一个数是否需要翻转,所以我们分两种情况来讨论就好了

    一开始我想着像3279那样枚举,可是1<<20次实在是太大了,结果TLE

    

#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;
static int bowls[21], if_flip[21];

int solve(void);
int get_step(int);

int main(void)//开关问题
{
    for (int i = 1; i <= 20; i++)
        scanf("%d", &bowls[i]);

    printf("%d
", solve());
    return EXIT_SUCCESS;
}
int solve()//所有输入都能有一个固定的值
{
    //if_flip[i]:=i~i+1需要翻转就是1,否则就是0
    int sum = 0, res = INT_MAX;

    memset(if_flip, 0, sizeof(if_flip));
    res = min(res, get_step(0));
    memset(if_flip, 0, sizeof(if_flip));
    res = min(res, get_step(1));

    return res;
}

int get_step(int sum)//关键问题就是第一个要不要翻,如果要翻那就是0,否则就是1
{
    int i, res = sum; if_flip[1] = sum;
    for (i = 2; i <= 20; i++)
    {
        if ((sum + bowls[i - 1]) % 2 == 1)
        {
            res++;
            if_flip[i] = 1;
        }
        sum += if_flip[i];
        sum -= if_flip[i - 2];
    }
    if ((bowls[20] + sum) % 2 == 1)
        return INT_MAX;
    else return res;
}

  

  

原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/5155387.html