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;
}