算法题:德才论

题目描述

宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之

小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人。”

现给出一批考生的德才分数,请根据司马光的理论给出录取排名。

输入描述:

输入第1行给出3个正整数,分别为:N(<=105),即考生总数;L(>=60),为录取最低分数线,即德分和才分均不低于L的考生才有资格

被考虑录取;H(<100),为优先录取线——德分和才分均不低于此线的被定义为“才德全尽”,此类考生按德才总分从高到低排序;才分不到

但德分到线的一类考生属于“德胜才”,也按总分排序,但排在第一类考生之后;德才分均低于H,但是德分不低于才分的考生属于“才德兼

亡”但尚有“德胜才”者,按总分排序,但排在第二类考生之后;其他达到最低线L的考生也按总分排序,但排在第三类考生之后。

随后N行,每行给出一位考生的信息,包括:准考证号、德分、才分,其中准考证号为8位整数,德才分为区间[0, 100]内的整数。数字间以空格分隔。

输出描述:

输出第1行首先给出达到最低分数线的考生人数M,随后M行,每行按照输入格式输出一位考生的信息,考生按输入中说明的规则从高到低排序。当某类考生中有多人

总分相同时,按其德分降序排列;若德分也并列,则按准考证号的升序输出。

输入例子:

14 60 80

10000001 64 90

10000002 90 60

10000011 85 80

10000003 85 80

10000004 80 85

10000005 82 77

10000006 83 76

10000007 90 78

10000008 75 79

10000009 59 90

10000010 88 45

10000012 80 100

10000013 90 99

10000014 66 60

输出例子:

12

10000013 90 99

10000012 80 100

10000003 85 80

10000011 85 80

10000004 80 85

10000007 90 78

10000006 83 76

10000005 82 77

10000002 90 60

10000014 66 60

10000008 75 79

10000001 64 90

#include <iostream>
#include <map>
#include <string.h>
using namespace std;

方案一:借助map。
struct Node
{
    char *schoolNum;
    int Ldata;
    int Hdata;
    Node(){}
    Node(const char *str, int l, int h) :schoolNum(new char[strlen(str) + 1])
    {
        strcpy(schoolNum, str);
        Ldata = l;
        Hdata = h;
    }
};
struct Cheigh
{
    bool operator()(Node nd1, Node nd2)
    {
        if ((nd1.Ldata +nd1.Hdata) > (nd2.Hdata + nd2.Ldata))
        {
            return true;
        }
        else
        {
            if ((nd1.Ldata + nd1.Hdata)<(nd2.Hdata + nd2.Ldata))return false;
            else
            {
                return string(nd1.schoolNum)>string(nd2.schoolNum);
                //题中分数如果相同还要比较学号。
            }
        }
    }
};
template<typename T1,typename T2,typename T3>
void Printf(map<T1,T2,T3> &mp)
{
    map<Node, int> ::iterator it = mp.begin();
    while (it != mp.end())
    {
        cout << it->first.schoolNum << " " << it->first.Ldata << " " << it->first.Hdata << endl;
        it++;
    }
}
int main()
{
    map<Node, int,Cheigh> mp1;//才德全尽。
    map<Node, int,Cheigh> mp2;//得胜才。
    map<Node, int,Cheigh> mp3;//才德兼亡”但尚有“德胜才。
    map<Node, int,Cheigh> mp4;//其他同学.

    int n;
    int numL, numH;
    cin >> n >> numL >> numH;

    int count = n;
    char *inputStr = new char[10];
    int a, b;
    while (n--)
    {
        cin >> inputStr >> a >> b;
        if (a >= numL && b >= numL)
        {
            if (a >= numH && b >= numH)
            {
                Node sNode(inputStr, a, b);
                mp1.insert(pair<Node,int>(sNode,0));
            }
            else if (a >= numH && b < numH)
            {
                Node sNode(inputStr, a, b);
                mp2.insert(pair<Node,int>(sNode,0));
            }
            else if (a < numH && b < numH && b <= a)
            {
                Node sNode(inputStr, a, b);
                mp3.insert(pair<Node,int>(sNode,0));
            }
            else
            {
                Node sNode(inputStr, a, b);
                mp4.insert(pair<Node,int>(sNode,0));
            }
        }
        else
        {
            count--;
        }
    }
    cout << count << endl;
    Printf<Node,int,Cheigh>(mp1);
    Printf<Node,int,Cheigh>(mp2);
    Printf<Node,int,Cheigh>(mp3);
    Printf<Node, int,Cheigh>(mp4);
    return 0;
}

方案二:自定义堆。
#include <iostream>
#include <string.h>
using namespace std;

struct Node
{
    char *schoolNum;
    int Ldata;
    int Hdata;
    Node(){}
    Node(const char *str,int l,int h) :schoolNum(new char[strlen(str) + 1])
    {
        strcpy(schoolNum,str);
        Ldata = l;
        Hdata = h;
    }
    bool operator<(const Node nd)
    {
        if ((Ldata + Hdata) < (nd.Hdata + nd.Ldata))
        {
            return true;
        }
        else
        {
            if ((Ldata + Hdata)>(nd.Hdata + nd.Ldata))return false;
            else
            {
                return string(schoolNum)<string(nd.schoolNum);
                //题中分数如果相同还要比较学号。
            }
        }
    }
    friend ostream& operator<<(ostream &_O, const Node &od)
    {
        _O << od.schoolNum << " " << od.Ldata << " " << od.Hdata << endl;
        return _O;
    }
};

template<typename Type>
class Heap
{
public:
    Heap(int n) :heap(new Node[n])
    {
        size = 0;
    }
    void Insert(Type &val)
    {
        heap[size++] = val;
        int n = size / 2;
        while (n>=0)
        {
            SetNew(heap,n);//调整。
            n--;
        }
    }
    void SetNew(Node *heap,int n)
    {
        int i = n;
        int j = 2 * i + 1;
        while (j < size)
        {
            if (j + 1 < size && heap[j] < heap[j + 1])
            {
                j = j++;
            }
            if (heap[i] < heap[j])
            {
                Node temp = heap[i];
                heap[i] = heap[j];
                heap[j] = temp;
            }
            i = j;
            j = i * 2 + 1;
        }
    }
    void Printf()
    {
        while (size)
        {
            cout << heap[0] << endl;
            heap[0] = heap[size - 1];
            size--;
            SetNew(heap,0);//忘记调整,找了半天错误。
        }
    }
private:
    Type *heap;
    int size;
};
int main()
{
    int n;
    int numL, numH;
    cin >> n >> numL >> numH;

    Heap<Node> hp1(n);//才德全尽。
    Heap<Node> hp2(n);//得胜才。
    Heap<Node> hp3(n);//才德兼亡”但尚有“德胜才。
    Heap<Node> hp4(n);//其他同学.
    int count = n;
    char *inputStr = new char[10];
    int a , b;
    while (n--)
    {
        cin >> inputStr >> a >> b;
        if (a >= numL && b >= numL)
        {
            if (a >= numH && b >= numH)
            {
                Node sNode(inputStr,a,b);
                hp1.Insert(sNode);
            }
            else if (a >= numH && b < numH)
            {
                Node sNode(inputStr, a, b);
                hp2.Insert(sNode);
            }
            else if (a < numH && b < numH && b <= a)
            {
                Node sNode(inputStr,a,b);

                hp3.Insert(sNode);
            }
            else
            {
                Node sNode(inputStr, a, b);
                hp4.Insert(sNode);
            }
        }
        else
        {
            count--;
        }
    }
    cout << count << endl;
    hp1.Printf();
    hp2.Printf();
    hp3.Printf();
    hp4.Printf();
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-07 17:47:06

算法题:德才论的相关文章

笔试算法题(09):查找指定和值的两个数 &amp; 构造BST镜像树

出题:输入一个已经升序排序的数组和一个数字:要求在数组中查找两个数,这两个数的和正好等于输入的那个数字,输出任意一对数字就可以,要求时间复杂度是O(n): 分析:对于升序排序的数组{-i-j-k-m--},只有可能是i+m=j+k(j和k可能是同一个数),所以可以从两边往中间收缩而忽视其他交叉相加的情况: 解题: 1 void FindSumFactor(int *array, int length, int sum) { 2 int left=0, right=length-1; 3 whil

笔试算法题(08):输出倒数第K个节点

出题:输入一个单向链表,要求输出链表中倒数第K个节点 分析:利用等差指针,指针A先行K步,然后指针B从链表头与A同步前进,当A到达链表尾时B指向的节点就是倒数第K个节点: 解题: 1 struct Node { 2 int v; 3 Node *next; 4 }; 5 Node* FindLastKth(Node *head, int k) { 6 if(head==NULL) { 7 printf("\nhead is NULL\n"); 8 exit(0); 9 } 10 Nod

笔试算法题(07):还原后序遍历数组 &amp; 半翻转英文句段

出题:输入一个整数数组,判断该数组是否符合一个二元查找树的后序遍历(给定整数数组,判定其是否满足某二元查找树的后序遍历): 分析:利用后序遍历对应到二元查找树的性质(序列最后一个元素必定是根节点,从左向右第一个比根节点大的元素开始直到根节点之前的所有元素必定在右子树,之前的所有元素必定在左子树): 解题: 1 bool PostOrderCheck(int *array, int i, int j) { 2 /** 3 * 如快速排序一样,解决小子文件 4 * */ 5 if(j-i+1 ==

java基础算法题

为了提高自己的代码能力和算法能力,我决定每天学习一道算法题,吸收前辈思想. [程序1] TestRabbit.java 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 程序分析:兔子数量的规律为数列:1,1,2,3,5,8,13.....其实就是斐波那契数列  使用递归就可以实现 1 /** 2 * 兔子问题 3 * 2016/5/9 4 * 斐波那契数列求值 5 *题目:古典问题:有一对兔子,

ios 算法题

1兔子算法题 兔子可以跳一步2步或者3步,问跳到100有多少种跳法? // 兔子可以跳一步2步或者3步 // 问跳到100有几种跳法 /* 分析1 两个变量,X*2+Y*3=100. X最大为50,X最小为2 Y最大为32.最小为0 分析2 某个情景分析:假设X=35,Y为10时, 虽然知道了数量,但是兔子的35小步,和10大步的顺序是怎样的? 应为组合-> 45个节点中,选择10个放三步的.那就是简单的C(45 10).变成阶乘,就解得出来. */ double temp=0.0f; for

[solution]腾讯TEG_计算广告组_算法题

度娘笔试归来,题目实打实的,感觉真心不易,上百号人就抢那么几个坑......只恨自己平时积累太少啊~ 故曝一道鹅厂面试用的算法题(当时我就死在了这题上),来为度娘家攒一下RP~ 题目: 对于长度为N的一个无序的数组a[1..N],请将a进行排序,要求所有正数都排在0之前,所有负数都排在0之后(如果没有0,则所有正数排在负数前) 要求时间复杂度O(N),空间复杂度O(1) 题目不难,但给思考的时间很短,大约不到5分钟吧.当时脑子比较短路,于是只给出了O(n) O(n)复杂度的算法,然后就被面试官挂

算法题——翻转链表中的一段

题目:给出一个链表中的两个指针p1和p2,将其之间的结点翻转. 思路:可以通过交换结点内的值来实现结点的翻转,空间为O(N):如果要求不能交换值,那么仅凭p1和p2是无法翻转的,只能交换两个指针之间的链表. 代码: 交换值: 1 struct ListNode 2 { 3 int val; 4 ListNode *next; 5 }; 6 7 void reverseNodes(ListNode *p1, ListNode *p2) { 8 if ( p1 == NULL || p2 == NU

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

一天一道算法题---6.26---二分查找

感谢微信平台---一天一道算法题----每天多一点进步-- 好累啊  现在在用win7自带的输入法 打起来真麻烦 快点把这2天的搞完就重装了 还是直接来源于----〉 待字闺中 分析 给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复,请给出方法,找到这个Magic Index.更进一步,当A中允许有重复的元素,该怎么办呢? 没有重复元素的情况 一些同学在遇到这个题目的时候,往往会觉得比较简单.

一天一道算法题--6.25--无定义

感谢微信平台---一天一道算法题--每天多一点进步---- 其实今天我接下去补上的几题都来自---待字闺中 所以我就原封不动的将它的题目与分析搬过来了 原题 给定一个数组,我们可以找到两个不相交的.并且是连续的子数组A和B,A中的数字和为sum(A), B中的元素和为sum(B).找到这样的A和B,满足sum(A) - sum(B)的绝对值是最大的. 例如:[2, -1 -2, 1, -4, 2, 8]划分为A=[-1, -2, 1, -4], B=[2, 8], 最大的值为16 分析 如果没有