CCF-201412-3-集合竞价

这道题不算是模拟,算数学题吧。这道题也是要细心。

思路

  1. 定的开盘价要使得买单和卖单的成交量最大就是尽可能多的把买单和买单进行匹配。成交量就是买单数和卖单数的最小值。
  2. 如图
    CCF-201412-3-集合竞价_第1张图片
    从buy买价开始找开盘价,每一个开盘价,从开盘价往上求出总买单数,往下找出总卖单数,找买卖单最小值,更新最大卖单数。

注意
为什么要从买单开始找开盘价,而不是暴力的每个价格试?
可以证明开盘价永远在买单中。简单的举个栗子,假定客人买东西有10元,东西成本卖5元,给你定价,你会定多少才挣钱?肯定10元啊。所以定价是看客人有多少钱,一样的道理,开盘价永远看买单的价格。
用图说话,看下图,稍微改了下数据。在价格轴上,定价杆(开盘价)在某个价格区间之内都可以达到最大交易量,当然就把杆往上抬,碰到买价为止,所以一定从买价中找开盘价。
CCF-201412-3-集合竞价_第2张图片

ip = []
cancel_list = []
try:
    while True:
        s = input().split()
        if s[0] == 'cancel':
            cancel_list.append(int(s[1]) - 1)
        ip.append(s)
except EOFError:
    pass

buy, sell = {}, {}
for i in range(len(ip)):
    if i not in cancel_list and ip[i][0] != 'cancel':
        if ip[i][0] == 'buy':
            if float(ip[i][1]) in buy:
                buy[float(ip[i][1])] += int(ip[i][2])
            else:
                buy[float(ip[i][1])] = int(ip[i][2])
        else:
            if float(ip[i][1]) in sell:
                sell[float(ip[i][1])] += int(ip[i][2])
            else:
                sell[float(ip[i][1])] = int(ip[i][2])

buyKeys = reversed(sorted(buy.keys()))
sellKeys = sorted(sell.keys())
maxPrice, maxDeal = 0, 0  # 最大开盘价 最大成交量
buyNum = 0  # 买单量
for buyP in buyKeys:
    buyNum += buy[buyP]
    sellNum = 0  # 卖单量
    for sellP in sellKeys:
        if sellP > buyP:
            break
        sellNum += sell[sellP]
    deal = min(buyNum, sellNum)  # 成交量
    if deal > maxDeal:
        maxDeal = deal
        maxPrice = buyP
print('%.2f' % maxPrice, maxDeal)

.

方法二:
用队列做。买单从大到小排序,卖单从小到大排序,买单和买单队首之间比较,买价大于等于买价,就交易。总交易量自加本次交易量,最大交易价就是买单此时的价格,每交易一单,交易价就更新为此时的买价。双方减去交易量,该买单或卖单交易完(股数为0)分别就出队,直到某一队列(买单或卖单)为空或买单小于卖单的时候,就终止交易。

python代码

ip = []
cancel_list = []
try:
    while True:
        s = input().split()
        if s[0] == 'cancel':
            cancel_list.append(int(s[1]) - 1)
        ip.append(s)
except EOFError:
    pass

buy, sell = {}, {}
for i in range(len(ip)):
    if i not in cancel_list and ip[i][0] != 'cancel':
        if ip[i][0] == 'buy':
            if float(ip[i][1]) in buy:
                buy[float(ip[i][1])] += int(ip[i][2])
            else:
                buy[float(ip[i][1])] = int(ip[i][2])
        else:
            if float(ip[i][1]) in sell:
                sell[float(ip[i][1])] += int(ip[i][2])
            else:
                sell[float(ip[i][1])] = int(ip[i][2])

buyKeys = list(reversed(sorted(buy.keys())))
sellKeys = list(sorted(sell.keys()))

totalDeal = 0
maxPrice = 0
while buyKeys and sellKeys and buyKeys[0] >= sellKeys[0]:
    maxPrice = buyKeys[0]
    deal = min(buy[buyKeys[0]], sell[sellKeys[0]])
    totalDeal += deal;
    buy[buyKeys[0]] -= deal
    sell[sellKeys[0]] -= deal
    if buy[buyKeys[0]] == 0:
        buyKeys.pop(0)
    if sell[sellKeys[0]] == 0:
        sellKeys.pop(0)
print('%.2f' % maxPrice, totalDeal)

你可能感兴趣的:(CCF)