[算法题]小朋友分糖问题

[算法题]小朋友分糖问题

问题:现在有n个小朋友坐成一排,每个小朋友都有一个竞赛得分,现在要根据竞赛得分给小朋友分糖,要求是相邻坐着的小朋友,分数高的小朋友的糖要比分数低的小朋友糖多(小朋友是随机坐的,也就是分数没排序),相邻的两个小朋友分数如果相同,那么得到的糖也要相同,现在程序要给出最少需要多少糖。

输入要求:

  1. 第一行输入一共有几个小朋友
  2. 第二行输入每个小朋友的竞赛分数,用空格隔开每个分数。

如:

3
1 2 2

应该到得到输出:5

解释:糖的分配情况 1 2 2,因为第一个分数最低,他得到1,第二个比第一个分数高,所以得到的糖也要比第一个多所以是2,第三个和第二个分数相同,所以得到的糖也要相同,所以也是2。

4
3 5 5 2

应该得到输出:6

解释:糖的分配情况1 2 2 1,因为与第一个相邻的小朋友分数都要高于它,所以他的粮要最少所以是1,第二个比第一个分数高,所以也要多拿一颗糖,所以是2。第三个和第二个相同,所以也要是2。第个四的分数低于附近的小朋友,所以也是1,因为第4个并不与第1个小朋友是邻居,所以他们之间不参与比较。

8

2 4 3 5 2 6 4 5

应该得到输出:12

糖的分配情况:1 2 1 2 1 2 1 2

根据题目我的程序是:

def initArr(arr):
    # -1代表没分配过
    min_x = min(arr)
    arr = [[x, 1 if x==min_x else -1] for x in arr]
    return arr

def get_condition_id(position,arr)->int:
    if position==len(arr)-1:
        return 2#列表结尾
    elif arr[position]==arr[position+1]:
        return 3#和列表当前位置之后元素相同
    elif position== 0:
        return 0#列表开头
    elif position!=0 and position!=len(arr)-1:
        return 1#列表中间


def fun_0(cur_index,n,arr):#列表开头
    if arr[n][0] < arr[n + 1][0]:
        arr[n][1] = 1
    elif arr[n][0] > arr[n + 1][0]:
        arr[n][1] = get_candy_num(n+1,arr) + 1
    return (cur_index,n)

def fun_1(cur_index,n,arr):#列表中间
    if arr[n - 1][0] > arr[n][0] < arr[n + 1][0]:
        arr[n][1] = 1
    else:
        if arr[n - 1][0] > arr[n][0] > arr[n + 1][0]:
            arr[n][1] = get_candy_num(n+1,arr) + 1
        elif arr[n - 1][0] < arr[n][0] < arr[n + 1][0]:
                arr[n][1] = arr[n - 1][1] + 1
        elif arr[n - 1][0] < arr[n][0] > arr[n + 1][0]:
            arr[n][1] = max(arr[n - 1][1], get_candy_num(n+1,arr)) + 1

    return (cur_index,n)

def fun_2(cur_index,n,arr):#列表结尾
    if arr[n - 1][0] > arr[n][0]:
        arr[n][1] = 1
    if arr[n - 1][0] < arr[n][0]:
            arr[n][1] = arr[n - 1][1] + 1
    return (cur_index,n)

def fun_3(cur_index,n,arr):
    #在这个函数里将相邻的相同元素视为一个元素
    same_val_index=[]#保存相同元素索引
    same_val_index.append(n)
    while n+1 < len(arr) and arr[n][0]==arr[n+1][0]:
        same_val_index.append(n+1)
        n+=1

    if same_val_index[-1] == len(arr)-1:#如果这是列表最后一位
        if arr[same_val_index[0]-1][0] > arr[same_val_index[0]][0]:
            for i in same_val_index:
                arr[i][1]=1
        else:
            for i in same_val_index:
                arr[i][1]=arr[same_val_index[0]-1][1]+1
    else:
        if arr[same_val_index[0]-1][0] > arr[same_val_index[0]][0] > arr[same_val_index[-1]+1][0] :
            arr[same_val_index[0]][1]=get_candy_num(same_val_index[-1]+1,arr)+1
        elif arr[same_val_index[0]-1][0] > arr[same_val_index[0]][0] < arr[same_val_index[-1]+1][0] :
            arr[same_val_index[0]][1]=1
        elif arr[same_val_index[0] - 1][0] < arr[same_val_index[0]][0] < arr[same_val_index[-1] + 1][0]:
            arr[same_val_index[0]][1]=arr[same_val_index[0] - 1][1]+1
        elif arr[same_val_index[0] - 1][0] < arr[same_val_index[0]][0] > arr[same_val_index[-1] + 1][0]:
            arr[same_val_index[0]][1]=max(arr[same_val_index[0] - 1][1],get_candy_num(same_val_index[-1] + 1,arr)) + 1
        for i in same_val_index:
            arr[i][1] = arr[same_val_index[0]][1]

    return (cur_index,n)

condition={
    0:fun_0,#列表开头
    1:fun_1,#列表中间
    2:fun_2,#列表结尾
    3:fun_3,#和列表当前位置之后元素相同
    #和列表当前位置之前元素相同
}

def get_candy_num(n,arr)->int:
    if arr[n][1] != -1: return arr[n][1]
    cur_index=n
    cur_index,n=condition[get_condition_id(n,arr)](cur_index,n,arr)
    if arr[cur_index][1] != -1:
        return arr[cur_index][1]
    else:
        return get_candy_num(n,arr)


def candies(n, arr):
    # Write your code here
    arr = initArr((arr))
    tot_candies = 0
    for i in range(n):
        tot_candies += get_candy_num(i, arr)#f_allocate(i,arr)#

    #with open(r'E:\practices\python\arr.json','w') as f:
    #    json.dump(arr,f)
    return tot_candies

PS:我认为这个函数最难的地方就是怎么处理比邻相同积分的小朋友。这个程序很臃肿,一时还想不到优化的方法

Comments are closed.