解题思路
-
题目要求:
个组进行比赛,每组至少发
奖金
- 每组只能看到相邻两组的成绩
- 如果成绩高于相邻组,奖金必须高于相邻组
- 求满足所有条件的最少总奖金
-
解题策略:
- 使用两次遍历:
- 从左到右:确保成绩高的比左边的奖金多
- 从右到左:确保成绩高的比右边的奖金多
- 最后求和得到总奖金
- 使用两次遍历:
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
while(cin >> n) {
// 读入成绩
vector<int> score(n);
for(int i = 0; i < n; i++) {
cin >> score[i];
}
// 初始化奖金数组,每人至少1w
vector<int> money(n, 1);
// 从左到右遍历
for(int i = 1; i < n; i++) {
if(score[i] > score[i-1]) {
money[i] = money[i-1] + 1;
}
}
// 从右到左遍历
for(int i = n-2; i >= 0; i--) {
if(score[i] > score[i+1] && money[i] <= money[i+1]) {
money[i] = money[i+1] + 1;
}
}
// 计算总和
long sum = 0;
for(int i = 0; i < n; i++) {
sum += money[i];
}
cout << sum << endl;
}
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int n = sc.nextInt();
// 读入成绩
int[] score = new int[n];
for(int i = 0; i < n; i++) {
score[i] = sc.nextInt();
}
// 初始化奖金数组,每人至少1w
int[] money = new int[n];
Arrays.fill(money, 1);
// 从左到右遍历
for(int i = 1; i < n; i++) {
if(score[i] > score[i-1]) {
money[i] = money[i-1] + 1;
}
}
// 从右到左遍历
for(int i = n-2; i >= 0; i--) {
if(score[i] > score[i+1] && money[i] <= money[i+1]) {
money[i] = money[i+1] + 1;
}
}
// 计算总和
long sum = 0;
for(int i = 0; i < n; i++) {
sum += money[i];
}
System.out.println(sum);
}
}
}
def min_total_money(n, scores):
# 初始化奖金数组,每人至少1w
money = [1] * n
# 从左到右遍历
for i in range(1, n):
if scores[i] > scores[i-1]:
money[i] = money[i-1] + 1
# 从右到左遍历
for i in range(n-2, -1, -1):
if scores[i] > scores[i+1] and money[i] <= money[i+1]:
money[i] = money[i+1] + 1
# 返回总和
return sum(money)
while True:
try:
n = int(input())
scores = [int(input()) for _ in range(n)]
print(min_total_money(n, scores))
except EOFError:
break
算法及复杂度
- 算法:贪心
- 时间复杂度:
- 需要两次遍历数组
- 空间复杂度:
- 需要存储奖金数组