又接触到贪心算法啦,这道题有两种算法思路,我用两个语言来写了一下,这也涉及到了一些动态规划的思路
一.从最后一个时间枚举,找到在这个时间内可以完成的最大分值的题
注意点:
1.数组下标从1开始记录表示第几个时间段以免后面弄混,因为题目给出 的时间段是从1开始的
2.从最后一个时间段开始枚举
为什么要从最后一个开始呢,可以理解为一个递归的思想,
n个时间段内的最优解=第n个时间段可以完成的最优解+n-1个时间段内可以完成的最优解
3.完成一道题后要将其分值设为0避免重复计算
C语言代码如下
//巧夺大奖,贪心算法 1
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
int i,j;
int T[n+1],R[n+1];
for(i=1;i<=n;i++){
scanf("%d",&T[i]);
}
for(i=1;i<=n;i++){
scanf("%d",&R[i]);
}
int max;//该时间段能获得最大奖励的游戏下标
int value;//该最大奖励的值
int sum=0;
//从最后一个时间段开始枚举
for(i=n;i>=1;i--){
max=0,value=0;
for(j=1;j<=n;j++){
if(T[j]>=i && R[j]>value){
max=j;
value=R[j];
}
}//遍历时间段
if(value!=0){//有最大的奖励
sum+=value;
R[max]=0;//防止重复计算
}
}
printf("%d",sum);
return 0;
}
二.分值大的在尽可能晚的时间内完成
知识点:
1.将几个列表一起打包的简单格式
game_info = [i, deadlines[i - 1], values[i - 1]]
2.对一个列表中的子列表进行排序,key是子列表的第三个元素,这里用到了lambda函数
sorted_games_info = sorted(games_info, key=lambda x: x[2], reverse=True)
3.遍历列表时,可以采用多对一的格式取出列表中的各个元素
game_index, game_deadline, game_value = game
4.对range进行逆向遍历时,第三个参数是必不可少的
for t in range(game_deadline, 0, -1):
python代码如下:
# 输入游戏数量
num_games = int(input())
# 初始化每个时间段的游戏安排情况
time_slots = {}
for i in range(1, num_games + 1):
time_slots[i] = 0
# 输入每个游戏的完成期限
deadlines = list(map(int, input().split()))
# 输入每个游戏的分值
values = list(map(int, input().split()))
# 打包游戏信息为一个列表
games_info = []
for i in range(1, num_games + 1):
game_info = [i, deadlines[i - 1], values[i - 1]]
games_info.append(game_info)
# 按分值从大到小排序游戏列表
sorted_games_info = sorted(games_info, key=lambda x: x[2], reverse=True)
# 初始化总得分
total_score = 0
# 遍历每个游戏
for game in sorted_games_info:
game_index, game_deadline, game_value = game
# 从游戏的截止期限开始往前找可以安排游戏的时间段
for t in range(game_deadline, 0, -1):
if time_slots[t] == 0:
# 找到可以安排游戏的时间段,安排该游戏并计分
time_slots[t] = 1
total_score += game_value
break
print(total_score)