http://bailian.openjudge.cn/dsj2017xly/
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
样例输入
2
1 20 14
1 30 3
2
1 10 99
3
2
2
0
样例输出
0
20
30
10
0
开始想着用两个优先队列做,分别定义一个最大堆和一个最小堆,但是这样出了问题,因为如果弹出最大堆的元素,那么该元素在最小堆中仍然存在,这与题意是不相符的。所以只好用题目中所说的“双队列”了。
下面是错误的两个优先队列的代码,虽然与本题不符,但是也把定义优先队列的方法记录下来,如下:
#include
#include
#include
#include
#include
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 maxx; //定义一个最大堆
priority_queue 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
#include
#include
#include
#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++;
}
}
}