ccf 20180-4再卖菜 python实现

刚刚开始学python,网上python题解太少,所以我也发一个吧。  初学者,写的不好请见谅。

题意:
问题描述
在一条街上有n个卖菜的商店,按1至n的顺序排成一排,这些商店都卖一种蔬菜。
第一天,每个商店都自己定了一个正整数的价格。店主们希望自己的菜价和其他商店的一致,第二天,每一家商店都会根据他自己和相邻商店的价格调整自己的价格。具体的,每家商店都会将第二天的菜价设置为自己和相邻商店第一天菜价的平均值(用去尾法取整)。
注意,编号为1的商店只有一个相邻的商店2,编号为n的商店只有一个相邻的商店n-1,其他编号为i的商店有两个相邻的商店i-1和i+1。
给定第二天各个商店的菜价,可能存在不同的符合要求的第一天的菜价,请找到符合要求的第一天菜价中字典序最小的一种。
字典序大小的定义:对于两个不同的价格序列(a1, a2, …, an)和(b1, b2, b3, …, bn),若存在i (i>=1), 使得ai<bi,且对于所有j<i,aj=bj,则认为第一个序列的字典序小于第二个序列。
输入格式
输入的第一行包含一个整数n,表示商店的数量。
第二行包含n个正整数,依次表示每个商店第二天的菜价。
输出格式
输出一行,包含n个正整数,依次表示每个商店第一天的菜价。
样例输入
8
2 2 1 3 4 9 10 13
样例输出
2 2 2 1 6 5 16 10
数据规模和约定
对于30%的评测用例,2<=n<=5,第二天每个商店的菜价为不超过10的正整数;
对于60%的评测用例,2<=n<=20,第二天每个商店的菜价为不超过100的正整数;
对于所有评测用例,2<=n<=300,第二天每个商店的菜价为不超过100的正整数。
请注意,以上都是给的第二天菜价的范围,第一天菜价可能会超过此范围。

第一次做这道题只会列表,没想到dfs,胡做得了十分,今天又做,看了好多题解,相关算法,终于做了出来,用的差分约束。、
相关的解释大家可以看一看这个:(https://blog.csdn.net/zhouzi2018/article/details/85268762)  或者网上搜索。


代码:
 

num = int(input())
new = [0]+list(map(int, input().split()))
graph = {}
for i in range(num+1):
    if i <= num-1:
        graph[i] = {i+1: 1}
    else:
        graph[i] = {}
for i in range(num+1):
    if i == 0:
        graph[i][i+2] = 2*new[1]
        if i+3 <= num:
            graph[i][i+3] = 3*new[2]
    elif i == num-2:
        graph[i][i+2] = 2*new[-1]
        if i-3 >= 0:
            graph[i][i-3] = -3*new[i-1]-2
    elif i == num:
        graph[i][i-2] = -2*new[i]-1
        if i-3 >= 0:
            graph[i][i-3] = -3*new[i-1]-2
    else:
        if i != num-2:
            if i+3 <= num:
                graph[i][i+3] = 3*new[i+2]
            if i-3 >= 0:
                graph[i][i-3] = -3*new[i-1]-2

这里丑陋的实现了一个邻接表,对于样例来说,打印出来是这样的:
{0: {1: 1, 2: 4, 3: 6}, 1: {2: 1, 4: 3}, 2: {3: 1, 5: 9}, 3: {4: 1, 6: 12, 0: -8}, 4: {5: 1, 7: 27, 1: -5},  \n 
5: {6: 1, 8: 30, 2: -11}, 6: {7: 1, 8: 26, 3: -14}, 7: {8: 1, 4: -29}, 8: {6: -27, 5: -32}}
比如对于   0: {1: 1, 2: 4, 3: 6}   表示0节点到1节点距离为1,到2节点距离为4,到3节点距离为6。

然后就是spfa算法:这里大家可以看 (https://blog.csdn.net/muxidreamtohit/article/details/7894298),很清楚。

list1 = [0]
for i in range(num):
    list1.append(-99999)
dui = [0]


def spfa():
    global graph
    global dui
    global list1
    if len(dui) == 0:
        for z in range(1, num + 1):
            print(list1[z] - list1[z - 1], end=' ')
        exit()
    else:
        start = dui.pop(0)
        for i in graph[start].keys():
            if graph[start][i]+list1[start] > list1[i]:
                list1[i] = graph[start][i]+list1[start]
                tianjia = True
                for j in dui:
                    if j == i:
                        tianjia = False
                        break
                if tianjia:
                    dui.append(i)
        spfa()


spfa()

list1中存放0节点到各节点的最大路长, 初始时设为-99999。dui为先进先出队列,初始时放入0。
打印时打印list1里每两个元素相减,即为第一天每天的菜价。


第一次发,写的很粗糙,但应该还能看。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值