zoukankan      html  css  js  c++  java
  • CCF201412-3 集合竞价(100分)


    试题编号: 201412-3
    试题名称: 集合竞价
    时间限制: 1.0s
    内存限制: 256.0MB
    问题描述:
    问题描述
      某股票交易所请你编写一个程序,根据开盘前客户提交的订单来确定某特定股票的开盘价和开盘成交量。
      该程序的输入由很多行构成,每一行为一条记录,记录可能有以下几种:
      1. buy p s 表示一个购买股票的买单,每手出价为p,购买股数为s。
      2. sell p s 表示一个出售股票的卖单,每手出价为p,出售股数为s。
      3. cancel i表示撤销第i行的记录。
      如果开盘价为p0,则系统可以将所有出价至少为p0的买单和所有出价至多为p0的卖单进行匹配。因此,此时的开盘成交量为出价至少为p0的买单的总股数和所有出价至多为p0的卖单的总股数之间的较小值。
      你的程序需要确定一个开盘价,使得开盘成交量尽可能地大。如果有多个符合条件的开盘价,你的程序应当输出最高的那一个。
    输入格式
      输入数据有任意多行,每一行是一条记录。保证输入合法。股数为不超过108的正整数,出价为精确到恰好小数点后两位的正实数,且不超过10000.00。
    输出格式
      你需要输出一行,包含两个数,以一个空格分隔。第一个数是开盘价,第二个是此开盘价下的成交量。开盘价需要精确到小数点后恰好两位。
    样例输入
    buy 9.25 100
    buy 8.88 175
    sell 9.00 1000
    buy 9.00 400
    sell 8.92 400
    cancel 1
    buy 100.00 50
    样例输出
    9.00 450
    评测用例规模与约定
      对于100%的数据,输入的行数不超过5000。

    问题链接:CCF201412试题

    问题描述:(参见上文)。

    问题分析:这是一个竞价匹配的问题。数据可以存储在结构数组中,但未必是好的方案。使用两个优先队列,一个用于存储购入订单,按价格从大到小排列;另外一个用于存储卖出订单,按价格从小到大排列;然后进行价格的匹配处理。

    程序说明:(略)。

    提交后得100分的C++语言程序如下:

    /* CCF201412-3 集合竞价 */
    
    #include <iostream>
    #include <queue>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    const int N = 5000;
    
    struct trading {
        int orderno;
        char t;
        float price;
        long long quantity;
        bool operator < (const trading& n) const {
            if(t == 's')
                return price > n.price;
            else // t == 'b'
                return price < n.price;
        }
    };
    
    bool cancelflag[N+1];
    
    int main()
    {
        trading t;
        priority_queue<trading> sell, buy;
        string strading;
    
        // 变量初始化
        memset(cancelflag, false, sizeof(cancelflag));
    
        // 输入数据
        int no = 0, tno;
    
        while(cin >> strading) {
            if(strading[0] == 'c') {
                // 设置交易号
                no++;
    
                // 输入取消的交易号
                cin >> tno;
    
                // 设置取消标志
                cancelflag[tno] = true;
            } else if(strading[0] == 'b' || strading[0] == 's') {
                // 设置交易号
                t.orderno = ++no;
    
                // 输入交易价格和数量
                cin >> t.price >> t.quantity;
    
                // 将交易分别放入买入和卖出的优先队列
                if(strading[0] == 'b') {
                    t.t = strading[0];
                    buy.push(t);
                } else {    // t.trading[0] == 's'
                    t.t = strading[0];
                    sell.push(t);
                }
            } else
                break;
        }
    
        // 集合竞价处理
        t.price = 0;
        t.quantity = 0;
        trading b, s;
        for(;;) {
            // 清除被取消的订单(同时将队头放在b和s中)
            while(!buy.empty()) {
                b = buy.top();
                if(cancelflag[b.orderno])
                    buy.pop();
                else
                    break;
            }
            while(!sell.empty()) {
                s = sell.top();
                if(cancelflag[s.orderno])
                    sell.pop();
                else
                    break;
            }
    
            // 买卖队列只要有一个为空,则处理结束
            if(buy.empty() || sell.empty())
                break;
    
            // 集合竞价处理
            if(b.price >= s.price) {
                t.quantity += min(b.quantity, s.quantity);
                t.price = b.price;
    
                if(b.quantity == s.quantity) {
                    buy.pop();
                    sell.pop();
                } else if(b.quantity > s.quantity) {
                    b.quantity -= s.quantity;
                    buy.pop();
                    buy.push(b);
                    sell.pop();
                } else {    // b.quantity < s.quantity
                    buy.pop();
                    s.quantity -= b.quantity;
                    sell.pop();
                    sell.push(s);
                }
            } else
                break;
        }
    
        // 输出结果
        printf("%.2f", t.price);
        cout << " " << t.quantity << endl;
    
        return 0;
    }
    
    /*
    测试样例:
    
    sell 8.88 100
    sell 8.88 175
    sell 9.00 400
    buy 8.88 400
    cancel 1
    sell 100.00 50
    8.88 175
    
    buy 9.25 100
    buy 8.88 175
    buy 9.00 400
    sell 8.88 400
    cancel 1
    buy 100.00 50
    9.00 400
    
    buy 9.25 100
    buy 8.88 175
    buy 9.00 400
    sell 8.79 1501
    cancel 1
    cancel 2
    9.00 400
    
    buy 9.25 110
    buy 8.88 300
    buy 18.88 200
    sell 8.88 201
    sell 9.25 100
    9.25 301
    */


  • 相关阅读:
    关于Dockerfile
    hiho一下 第六十四周 Right-click Context Menu
    hdu2642二维树状数组单点更新+区间查询
    东大oj-1511: Caoshen like math
    东大OJ-1588: Routing Table
    东大oj-1591 Circle of friends
    2015年辽宁省赛Interesting Tree
    东大OJ-1544: GG的战争法则
    迷宫问题-广度优先搜索
    vijos P1009清帝之惑之康熙
  • 原文地址:https://www.cnblogs.com/tigerisland/p/7564166.html
Copyright © 2011-2022 走看看