北大大数据机试题

来源:互联网 发布:h5制作软件下载 编辑:程序博客网 时间:2024/06/15 14:36

http://bailian.openjudge.cn/dsj2017xly/

下面是G题,正好试一下优先队列

G:双队列

总时间限制:
1000ms
内存限制:
65536kB

描述

系统A用来维护客户。每个客户的id用一个正整数K来表示,当客户进入系统时用P来表示此用户的优先度。这个系统有以下请求0  系统停止运行1 K P  优先度为P的客户K进入系统2 找到优先度最高的客户,然后此客户离开系统3 找到优先度最低的客户,然后此客户离开系统

输入
每行包括一个请求,最后一行包括一个停止请求(代码0)。对于添加客户请求(代码1),优先度都是唯一的。客户的表示K小于106,优先度P小于107,一个客户可能会被添加多次,每次的优先度可能不同。
输出
对于每个请求2和3,程序必须输出一行。这行包括此请求中找到客户的id。如果系统中没有客户,输出0
样例输入

21 20 141 30 321 10 993220

样例输出

02030100

思路:

开始想着用两个优先队列做,分别定义一个最大堆和一个最小堆,但是这样出了问题,因为如果弹出最大堆的元素,那么该元素在最小堆中仍然存在,这与题意是不相符的。所以只好用题目中所说的“双队列”了。
下面是错误的两个优先队列的代码,虽然与本题不符,但是也把定义优先队列的方法记录下来,如下:

#include <iostream>#include <cstring>#include <algorithm>#include <queue>#include <cstdio>using namespace std;struct client{//重载运算符,使他成为最小堆,    int id;//父节点元素都比子节点大,根节点是最大值    int pri;    client(int i, int p){ //构造方法        id = i;        pri = p;    }    //重载运算符,定义<    bool operator < (const client &a) const{  //这个地方的const,必须要加        if (pri < a.pri) return true;        else return false;    }};struct client2{  //重载运算符,使他成为最小堆,    int id;     //父节点元素都比子节点小,根节点是最小值    int pri;    client2(int i, int p){        id = i;        pri = p;    }    bool operator < (const client2 &a) const{        if (pri < a.pri) return false;        else return true;    }};int main(){    //按照这个题目,定义两个优先队列是错误的,因为    //如果选择2,就会从最大堆里弹出,但是该用户仍然存在在最小堆里    //所以应该用双向队列    priority_queue<client> maxx;  //定义一个最大堆    priority_queue<client2> minn; //定义一个最小堆    int p, k, quest;    while (true){        cin >> quest;        if (quest == 0) break;        if (quest == 1) {            cin >> k >> p;            client c(k, p);            client2 d(k, p);            minn.push(d);            maxx.push(c);        }        if (quest == 2){  //控制最大堆            if (maxx.empty()) cout << "0" << endl;            else {                cout << maxx.top().id << endl;                maxx.pop();            }        }        if (quest == 3){  //控制最小堆            if (minn.empty()) cout << "0" << endl;            else {                cout << minn.top().id << endl;                minn.pop();            }        }    }    return 0;}

D:特殊密码锁
总时间限制: 1000ms 内存限制: 1024kB
描述
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。

然而让人头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。

当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。

输入
两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。
输出
至少需要进行的按按钮操作次数,如果无法实现转变,则输出impossible。
样例输入
011
000
样例输出
1

思路:

这个题,开始我想着因为n才30,直接深度优先搜索算了,应该不会超时,但是看了一下其他人的题解,发现原来直接贪心算法就可以。从第一个位置开始,如果不同,就按下第二个的按钮,这样就将n个元素的问题转换为n-1个,然后依次这样做。(下面的代码还没有编译运行)

#include "stdafx.h"#include <algorithm>#include <cstring>#include <cstdio>#include <iostream>#include "stdio.h"using namespace std;int main() {    char a1[30];    char a2[30];    int i = 0;    while (true) {        scanf("%c", &a1[i++]);        if (a1[i - 1] == '\n') break;    }    int j = 0;     while (true) {        scanf("%c", &a2[j++]);        if (a2[j - 1] == '\n') break;    }    int ans = 0;    for (int k = 0; k < i; k++) {        if (k == i - 1) {            if (a1[k] != a2[k])  cout << "impossible" << endl;            else cout << ans << endl;        }        if (a1[k] == a2[k]) continue;        else {            a1[k + 1] ^= 1;  //异或  a1[k+1] = 1 - a1[k+1]            a1[k] ^= 1;            a1[k + 2] ^= 1;            ans++;        }    }}
原创粉丝点击