Codeforces

本文探讨了三个编程问题:BestPermutation通过优化排列最大化和;ColoredBalls挑战最小步骤染色;C.MainakandArray寻找数组操作后最大差值。通过策略分析和代码实现,揭示了解决这些问题的关键思路和技术应用。
摘要由CSDN通过智能技术生成

Problem A:Best Permutation

 input:

3

4

5

6

output:

2 1 3 4

1 2 3 4 5

4 5 1 2 3 6

 说实话现在难的不光是题,难的还有翻译

简单的翻译一下上面的题目:求最好的排列。最好的排列指的是在1~N的N个数的排列中,我们在保证满足最大和的情况下,写出相应的排列。这个最大的和指的是(如果当前的这个和sum小于当前位置上的数x,那么sum+=x,否者的话sum重新置为零。最初的时候sum为0)

思路分析:

首先我们分析题目给出的这几组数据,我们可以简单的总结出一个小规律,就是每个排列的最大和是这个排列中最大的两个数的和。这个一出,问题直接就简化成了如何保证我们最大和就是最后两个数的和,即让最后两个数前面的那个数小于他前面的那个sum,使得我们可以在最大的两个数前sum置为0.在我们不断的探索中我么会发现,连续的三个数就会被置为0(包括1,2,3),由此这个题的基本思路就出来了。

首先我们根据每个排列数目模3 的结果将这个题分为三种情况

1.当N%3=1时,这时候我们如果不去处理这个排列,那么他的最大和是倒数3.4个数的和,便不会满足题目要求,为了它能够满足题目要求我们让前四个数满足sum为零,这样的话我们便可以避免掉这多余的一个数的影响。(2 1 3 4)

2.当N%3=2时,这时候我们会现,当我们按照重1~n的正常排列的时候,sum在倒数第三个数的时候正好会被置为0,这时候我们求出的正好就是最后两个数的和,即最大的和。

3.当N%3=0时,我们会发现,当我们按照1~n正常的排列的时候,我们求出的是倒数第三个和单数第二个的和,而不是我们所需要的最大和,那么就和第一种情况一样,我们要将前四个数改变一下顺序,使得sum在倒数第三个位置上被置为0.(4,1,3,2)

代码如下:

#include <iostream>
#include <algorithm>
using namespace std;

void f(int n)
{
    if (n % 3 == 2)
    {
        for (int i = 1; i <= n; i++)
            cout << i << " ";
        cout << endl;
    }
    if (n % 3 == 1)
    {
        printf("2 1 3 4 ");
        for (int i = 5; i <= n; i++)
        {
            cout << i << " ";
        }
        cout << endl;
    }
    if (n % 3 == 0)
    {
        printf("4 1 3 2 ");
        for (int i = 5; i <= n; i++)
            cout << i << " ";
        cout << endl;
    }
}
int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        int x;
        cin >> x;
        f(x);
    }
    return 0;
}

B. Colored Balls: Revisited

input:

3

3

1 1 1

1

9

2

4 7

output:

3
1
2

简单的翻译一下题目:

有一个包里面有许多不同颜色的球,这些球的数量和是odd奇数 ,现在我们要对这个包里面的球做move处理(每次拿走两个不同颜色的球),求出最后剩下的那种球的颜色。

思路分析:

当我看到这个题我的第一想法便是贪心,我们先求出最多数量的那种球,接下来我们对于剩余的其他球分别进行move,最后我们会得到两种情况,一是正好只剩下最多的那些球,二是只有其余部分剩下一部分球和那个最多的球,然后两者进行move,最后只剩下最多的那些球。

代码如下:

#include <iostream>

using namespace std;

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        int n;
        cin >> n;
        int x, max = 0, pos = 0;
        for (int i = 0; i < n; i++)
        {
            cin >> x;
            if (x > max)
                max = x, pos = i + 1;
        }
        if (n == 1)
            puts("1");
        else
            cout << pos << endl;
    }
    return 0;
}

problem:C. Mainak and Array

input:

5
6
1 3 9 11 5 7
1
20
3
9 99 999
4
2 1 8 1
3
2 1 5

output:

10
0
990
7
4

简单的翻一下题目:

给我们一个数组,我们对这个数组进行特殊的操作(选取这个数组中的一段,对其进行后移操作,当处于最后一个时,会自动转换到第一个去),使得a[N]-a[1]取值最大,求出这个最大值。

思路分析:

首先我们做这个题我们要多看几组测试数据并多按照题目要求走几遍,我们可以得出我们进行的操作只有让[2,n]进行移动操作,或者让[1,n-1]进行移动,还有整体的移动,这三种情况。

代码:

#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        int n;
        cin >> n;
        int a[2010];
        for (int i = 1; i <= n; i++)
            cin >> a[i];

        int b = a[n] - a[1];
        for (int i = 1; i < n; i++)
        {
            b = max(b, a[n] - a[i]);//前n-1个数不断的转
            b = max(b, a[i + 1] - a[1]);//【2,n】区间内的数不断的转
            b = max(b, a[i] - a[i + 1]);//整体的转
        }
        cout << b << endl;
    }

    return 0;
}

problem:E. Image

input:

5
rb
br
cc
wb
aa
aa
ab
cd
yy
xx

output:

1
2
0
3
1

简单的解释一下题目的意思:

有一个2x2的格子,格子中可以填入不同颜色一共有26种(这不就是26个字母吗),我们可以将相邻的颜色块染色(包括对角线),最后我们要求的是染成一个颜色所需要的最少步骤。

思路分析:

这题猛的一看,我没大看明白,但是在我看了几组测试数据之后,我大体上明白了这个意思, 我又列出了当有四种不同的颜色的时候,三种不同的颜色的时候,两种不同颜色的时候的情况,然后我惊奇的发现,每种大情况所得到的结果其实是一样的!!!然后这个题我们就顺理成章的转换成了求一个2x2的格子种有几种不同的颜色。

代码如下:

#include <iostream>

using namespace std;

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        char s;
        int a[30];
        for (int i = 0; i < 30; i++)
            a[i] = 0;
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
            {
                cin >> s;
                a[s - 'a']++;
            }
        int num = 0;
        for (int i = 0; i < 30; i++)
            if (a[i])
                num++;

        if (num == 4)
            puts("3");
        if (num == 3)
            puts("2");
        if (num == 2)
            puts("1");
        if (num == 1)
            puts("0");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值