股票开盘的最大成交额-----一道不错的贪心算法题目

本篇文章非解题报告,只是发表一下本人的对该题的解题思路,在本算法中涉及了对数据的存储,筛选,排序,业务实现。

最后会附上个人写的代码,以满足多组测试示例,不知道是否是完全正确的。希望有看出问题的博友给出意见,或者针对本题有更好方法的,请给出提示,多谢!

ps:由于前两篇发到首页的文章,被管理员移除,说解题报告类型的文章不适合发布到首页。这篇文章而非解题报告,是什么呢?我也说不好了,先发一下吧,希望遇到交流者。

rePs:事情证明,我这篇还是解题报告类型的文章。在发到首页不到两分钟的时间又被移除了!希望不被加入黑名单!


问题如下:

  某股票交易所请你编写一个程序,根据开盘前客户提交的订单来确定某特定股票的开盘价和开盘成交量。
  该程序的输入由很多行构成,每一行为一条记录,记录可能有以下几种:
  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。


源码:

#include "stdafx.h"
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;

const int MIN = 0;

typedef struct Shares{
    //买或卖的价格
    double price;
    //股数
    int number;
    //false 表示买
    //true 表示卖
    bool buyOrSell;
    //是否被cancel
    bool enable;
    Shares()
    {
        price = 0.00;
        number = 0;
        buyOrSell = false;
        enable = true;
    }
};
int min(int num1, int num2);
//取消的第th条交易股
void cancelRecord(int th);
//从未分类的交易股,按照条件进行分类存储,并进行排序
void divTypeOfShares(int n, int &lenOfSell, int& lenOfBuy);
//计算结果
void computePriceAndMax(int n, double& perPrice, int& perNumber);

//存储输入的交易股,不区分买家还是卖家
Shares shares[10001];
//存储买家的交易股
Shares sharesBuy[5001];
//存储卖家的交易股
Shares sharesSell[5001];

//定义买家类型的交易股比较函数,用于排序
//主排序按照价格为关键字递增
//次排序按照购买股数作为关键字递减
bool cmpBuy(Shares buy1, Shares buy2)
{
    if (buy1.price != buy2.price)
        return buy1.price < buy2.price;
    else if (buy1.price == buy2.price)
        return buy1.number >= buy2.number;
}

//卖家类型的交易股同上
bool cmpSell(Shares sell1, Shares sell2)
{
    if (sell1.price != sell2.price)
        return sell1.price >= sell2.price;
    else if (sell1.price == sell2.price)
        return sell1.number >= sell2.number;
}

void main(void)
{
    char typeOfShares[10];
    double price;
    int number;
    int index = 1;

    double perPrice = 0.00;
    int perNumber = MIN;
    while (cin >> typeOfShares)
    {

        if (strcmp(typeOfShares, "buy") == 0)
        {
            cin >> price >> number;
            shares[index].buyOrSell = false;
            shares[index].price = price;
            shares[index].number = number;
            index++;
        }
        else if (strcmp(typeOfShares, "sell") == 0)
        {
            cin >> price >> number;
            shares[index].buyOrSell = true;
            shares[index].price = price;
            shares[index].number = number;
            index++;
        }
        else if (strcmp(typeOfShares, "cancel") == 0)
        {
            int recordth;
            cin >> recordth;
            cancelRecord(recordth);
        }
        else
        {
            computePriceAndMax(index - 1, perPrice, perNumber);
            cout << perPrice << ‘ ‘ << perNumber << endl;
        }
        memset(typeOfShares, 0, 10);
    }
}

int min(int num1, int num2)
{
    if (num1 <= num2)
        return num1;
    else
        return num2;
}

//取消的第th条交易股
void cancelRecord(int th)
{
    shares[th].price = 0.00;
    shares[th].number = 0;
    shares[th].enable = false;
}

//从未分类的交易股,按照条件进行分类存储,并进行排序
void divTypeOfShares(int n, int &lenOfSell, int& lenOfBuy)
{
    int i = 1, j = 0, k = 0;
    for (; i <= n; i++)
    {
        if (shares[i].buyOrSell == false && shares[i].enable == true)
            sharesBuy[j++] = shares[i];
        else if (shares[i].buyOrSell == true && shares[i].enable == true)
            sharesSell[k++] = shares[i];
    }

    lenOfBuy = j;
    lenOfSell = k;
    sort(sharesBuy, sharesBuy + lenOfBuy, cmpBuy);
    sort(sharesSell, sharesSell + lenOfSell, cmpSell);
}

void computePriceAndMax(int n, double& perPrice, int& perNumber)
{
    double tmpPrice;//临时存储最优的开盘价
    int sumBuy = 0, sumSell = 0;//买的总股数和卖的总股数
    int lenOfSharesBuy, lenOfSharesSell;//买家类型数组长度,卖家类型数组长度
    divTypeOfShares(n, lenOfSharesSell, lenOfSharesBuy);

    for (int i = 0; i < lenOfSharesBuy; i++)
    {
        /*由前面的买家交易股的排序知道当前的交易股,其价格是大于等于其前面的交易股的。
        那么如果它的股数比前面所有的交易股之和大或者相等,则无需购买前面的交易股。
        */
        if (sharesBuy[i].number > sumBuy)
        {
            tmpPrice = sharesBuy[i].price;
            sumBuy = sharesBuy[i].number;
        }
        else
            sumBuy += sharesBuy[i].number;
        sumSell = 0;
        for (int j = 0; j < lenOfSharesSell; j++)
        {
            //如果当前的卖家股的价格比开盘价高,则不能购买,跳过
            if (sharesSell[j].price > tmpPrice)
                continue;
            sumSell += sharesSell[j].number;
        }

        if (perNumber <= min(sumBuy, sumSell))
        {
            perNumber = min(sumBuy, sumSell);
            perPrice = tmpPrice;
        }

    }
}
时间: 2024-12-28 21:24:40

股票开盘的最大成交额-----一道不错的贪心算法题目的相关文章

一道SQL语句的面试题目

今天一个朋友发了一道题目给我,我把此题目贴出来,以便大伙看看,共同研究研究. 题目: 已知关系模式: 1.s (sno,sname) 学生关系.sno 为学号,sname 为姓名2.c (cno,cname,cteacher) 课程关系cno 为课程号,cname 为课程名,cteacher 为任课教师3.sc(sno,cno,scgrade) 选课关系.scgrade 为成绩要求实现如下5 个处理:1.找出没有选修过“李明”老师讲授课程的所有学生姓名2.列出有二门以上(含两门)不及格课程的学生

值得一做》一道类似于货车运输的题目(BZOJ3732)(easy+)

这是一道模板套模板的题目,只要会LCA和最小生成树就可以做,水题 直接先甩题目 Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000). 现在有 K个询问 (1 < = K < = 15,000). 每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值

一道算法题目, 二行代码, Binary Tree

June 8, 2015 我最喜欢的一道算法题目, 二行代码. 编程序需要很强的逻辑思维, 多问几个为什么, 可不可以简化.想一想, 二行代码, 五分钟就可以搞定; 2015年网上大家热议的 Homebrew 的作者 Max Howell 面试 Google 挂掉的一题, 二叉树反转, 七行代码, 相比二行代码, 情有可原! Problem: return the count of binary tree with only one child 想一想, 你要写几行, 六七行, 或小于十行? S

考考你!一道有趣的Javascript小题目

今天的内容很简单,给大家分享一个有趣的Javascript小题目. 题目很简单,就是填空: var a = ______; var b = a;alert(a==b); // alert "false" 请将程序补充完整,使得弹出的对话框显示为"false". 先答出的有奖哦 ^ ^ --------------------- 用简单而风趣的形式表达出自己的想法是我一直追求的目标(当然,目前还处于"XX主义初级阶段",还有很长的路要走). 如果你

记一道毫无思路的算法题

今天贤内给了我一道很实际的算法题,把我彻底难住了,实在想不出来,于是写此博文以记之. 背景是这样的,现在有一个付款明细的Excel,里面有为哪个发票,哪个公司应付多少钱的明细,明细数据是62条,现在知道我们已经付出的金额为Sum,请问到底哪些发票是已付款的. 这是62条明细数据: 653165.00 356029.11 220896.45 146362.00 1847670.00 3018518.91 1347553.07 145010.74 339784.84 199350.28 120611

记一道数字旋转排列算法题

记一道数字旋转排列算法题 面试的时候遇到一道算法题,当时没做出来,也没有什么思路.睡觉前突然想到解法,记录一下. 题的大意如下,数字以1开始,并围绕1做逆时针旋转,其中1的坐标为(0, 0),如下图所示: 要求给一个坐标,求其未知的数是多少?例:给出(1, 0),该坐标的数为2:给出(-1, -2),该坐标上的数为22. 说下解题思路,由点的坐标可以得出目标值所在的圈数p,比如5在第2圈,p的大小为坐标x或y较大绝对值n再+1,比如18为(-2,1),绝对值n为2,则18在第3圈(n+1),然后

刷题向》关于一道奇怪的贪心(田忌赛马)BZOJ1034

这道题一看就是一道贪心,比较简单,但是越容易的题考试的时候越容易错... 没什么好说的,一遍SORT之后,直接强行田忌赛艇(滑稽脸)就好啦. 注意在对比大小的时候不仅要从前还要从后同时,不过这两个情况的优先级(亲测)没什么差别. 传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1034 直接甩出题目&代码 Description 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选

Java - 一道关于Arrays.asList的题目

题目 有这样一道有趣的题目: final int[] test = new int[]{1,2,3,4}; final Integer[] test2 = new Integer[]{1,2,3,4}; final List list1 = Arrays.asList(test); final List list2 = Arrays.asList(test2); final List list3 = Arrays.asList(1,2,3,4); System.out.println(list1

一道JS的简单算法题

今天百度了一下腾讯的前端面试题,找了好久只有找到这道题,顺便mark一下 题目是这样的:有一组数字,从1到n,从中减少了3个数,顺序也被打乱,放在一个n-3的数组里,请找出丢失的数字,最好能有程序,最好算法比较快. 网上的答案有一些出入,整理如下 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transiti