蒟蒻萌新第一次发文章,还请大佬们指正!
A.Average Height
题意:
有多组数据,每次给一个数组
a
a
a,要求重新排序,使得
a
i
+
a
i
+
1
2
\frac {a_i+a_{i+1}}{2}
2ai+ai+1是整数的
i
i
i尽量的多,输出排序后的数组
a
a
a。
思路:
把数组
a
a
a中的奇数和偶数分开,奇数放在一块,偶数放在一块,就能使满足要求的
i
i
i最多。
AC代码
#include <bits/stdc++.h>
using namespace std;
int a[2007];
bool cmp(int x, int y)//奇数在前,偶数在后
{
return (x % 2 == 1 && y % 2 == 0);
}
int main()
{
int t;
cin >> t;
while (t--){
int n;
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
sort(a+1, a+1+n, cmp);
for (int i = 1; i <= n; i++){
cout << a[i] << " ";
}
cout << endl;
}
return 0;
}
B.TMT Document
题意:
有多组数据,每次给定给出一个字符串
s
s
s,如果能将
s
s
s划分成若干不相交的子序列,若每个子序列都是
T
M
T
TMT
TMT,则输出
Y
E
S
YES
YES;否则输出
N
O
NO
NO。
注:子序列的定义——如果字符串A可以通过删除几个(可能为零)字符从字符串b中获得,则字符串A是字符串b的子序列。
思路:
判断
N
O
NO
NO的“三步走”:
1.先计算字符串中
T
T
T和
M
M
M的个数,若
T
T
T的个数不为
M
M
M的个数的两倍,则输出
N
O
NO
NO;
2.从头开始到最后一个
M
M
M的位置,若到某个位置
T
T
T的个数小于M的个数,则输出
N
O
NO
NO;
3.从末尾开始到第一个
M
M
M的位置,若到某个位置
T
T
T的个数小于M的个数,则输出
N
O
NO
NO。
若这三步都过了,输出
Y
E
S
YES
YES。
AC代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin >> t;
while (t--){
int n;
string s;
cin >> n;
cin >> s;
//第一步:判断T和M的个数
int cnt1 = 0, cnt2 = 0;
for (int i = 0; i < n; i++){
if (s[i] == 'T'){
cnt1++;
}else if (s[i] == 'M'){
cnt2++;
}
}
if (cnt1 != 2*cnt2){
cout << "NO" << endl;
continue;
}
//定位第一个和最后一个M的位置
int l = n, r = -1;
for (int i = 0; i < n; i++){
if (s[i] == 'M'){
l = min(l, i);//l为第一个M的位置
r = max(r, i);//r为最后一个M的位置
}
}
//第二步:从头开始到最后一个M的位置,看到某个位置T的个数是否小于M的个数
int f1 = 1;
int t1 = 0, m1 = 0;
for (int i = 0; i <= r; i++){
if (s[i] == 'T'){
t1++;
}else if (s[i] == 'M'){
m1++;
if (m1 > t1){
f1 = 0;
break;
}
}
}
if (f1 == 0){
cout << "NO" << endl;
continue;
}
//第三步:从末尾开始到第一个M的位置,到某个位置T的个数是否小于M的个数
int f2 = 1;
int t2 = 0, m2 = 0;
for (int i = n-1; i >= l; i--){
if (s[i] == 'M'){
m2++;
if (m2 > t2){
f2 = 0;
break;
}
}else if (s[i] == 'T'){
t2++;
}
}
if (f2 == 0){
cout << "NO" << endl;
continue;
}
//若这三步都过了,输出YES
cout << "YES" << endl;
}
return 0;
}
C.The Sports Festival
题意:
给定一个数组
a
a
a,每次拿出来任意一个数(注意每次选的数不同),定义
d
i
=
m
a
x
(
a
1
+
a
2
+
.
.
.
+
a
i
)
−
m
i
n
(
a
1
+
a
2
+
.
.
.
+
a
i
)
d_i=max(a_1+a_2+...+a_i) - min(a_1+a_2+...+a_i)
di=max(a1+a2+...+ai)−min(a1+a2+...+ai),要求对
a
a
a重新排序,使得
d
1
+
d
2
+
.
.
.
+
d
n
d_1+d_2+...+d_n
d1+d2+...+dn的值最小,输出最小的
d
1
+
d
2
+
.
.
.
+
d
n
d_1+d_2+...+d_n
d1+d2+...+dn的值。
思路:
先对原数组
a
a
a进行排序,再用区间
d
p
dp
dp。设
d
p
[
l
]
[
r
]
dp[l][r]
dp[l][r]代表区间
[
l
,
r
]
[l,r]
[l,r]内的元素的最小的
d
d
d之和。
dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + a[j] - a[i];
即“区间
[
i
+
1
,
j
]
[i+1,j]
[i+1,j]内的元素的最小的
d
d
d之和”与“区间
[
i
,
j
−
1
]
[i,j-1]
[i,j−1]内的元素的最小的
d
d
d之和”两者更小的那一个,加上
a
[
j
]
−
a
[
i
]
a[j]-a[i]
a[j]−a[i],就是区间
[
i
,
j
]
[i,j]
[i,j]内的元素的最小的
d
d
d之和。
最后输出
d
p
[
1
]
[
n
]
dp[1][n]
dp[1][n]即为答案。
AC代码
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll a[2007], dp[2007][2007];//三年oi一场空,不开longlong见祖宗
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
sort(a+1, a+1+n);
memset(dp, 0, sizeof(dp));//清零
for (int i = n-1; i >= 1; i--){
for(int j = i+1; j <= n; j++){
dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + a[j] - a[i];
}
}
cout << dp[1][n] << endl;
return 0;
}