使用标准库的栈和队列时,先包含相关的头文件
#include<stack>
#include<queue>
定义栈如下:
stack<int> s;
定义队列如下:
queue<int> q;
栈提供了如下的操作
//s.empty() 如果栈为空返回true,否则返回false
//s.size() 返回栈中元素的个数
//s.pop() 删除栈顶元素但不返回其值
//s.top() 返回栈顶的元素,但不删除该元素
//s.push() 在栈顶压入新元素
队列提供了下面的操作
q.empty() 如果队列为空返回true,否则返回false
q.size() 返回队列中元素的个数
q.pop() 删除队列首元素但不返回其值
q.front() 返回队首元素的值,但不删除该元素
q.push() 在队尾压入新元素
q.back() 返回队列尾元素的值,但不删除该元素
栈: 例题 poj 2082 Terrible Sets
题意:
紧贴x轴有一些互相挨着的矩形,给定每个矩形的长宽,问它们可以形成的最大矩形是多少。
思路:
用栈来做,将矩形入栈,保持栈中的元素高度递增,如果即将入栈的高度data.h比栈顶元素的高度lasth小,则退栈。一直退到可以保持栈顶元素高度递增的那个元素x,在退栈过程中统计由lasth至x之间可以形成的最大矩形面积s,记录由lasth至x之间矩形总宽度totalw,在弹出这些元素之后再向栈中压入一个高度为data.h, 宽度为totalw + data.w的矩形,然后继续读入下一个矩形。最后再扫描一遍就好了。
代码:
#include <iostream>
#include <stack>
#include <cstdio>
using namespace std;
struct rec {//矩形
int w, h;//宽和高
}data;
int main() {
int n, ans, i, lasth, totalw, curarea;
while(scanf("%d", &n) && n != -1) {
ans = 0;
stack<rec>s;
lasth = 0;//上次进栈的矩形的高度
for(i = 0; i < n; i++) {
scanf("%d%d", &data.w, &data.h);
if (data.h >= lasth) {
s.push(data);//进栈
}else {
totalw = 0;//总宽
curarea = 0;//当前面积
while(!s.empty() && s.top().h > data.h) {
totalw += s.top().w;
curarea = totalw*s.top().h;
if (curarea > ans)
ans = curarea;
s.pop();
}
totalw += data.w;
data.w = totalw;
s.push(data);//新矩形压栈
}
lasth = data.h;
}
totalw = 0;
curarea = 0;
while(!s.empty()) {//最后再扫描一遍
totalw += s.top().w;
curarea = totalw*s.top().h;
if (curarea > ans)
ans = curarea;
s.pop();
}
printf("%d\n", ans);
}
return 0;
}
直接用数组来做;
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <stack>
using namespace std;
const int maxn = 50008;
long long h[maxn], len[maxn];
int main() {
long long res;
int n, wi, hi, i;
while(scanf("%d", &n) && (n+1)) {
i = 0;
res = 0;
while(n--) {
scanf("%d%d", &wi, &hi);
if (i == 0) {
h[i] = hi;
len[i++] = wi;
continue;
}
int tmp = 0;
if (h[i-1] > hi) tmp = 1;
while(h[i-1] > hi && i > 0) {
i--;
res = max(res, h[i]*len[i]);
}
for(int j = 0; j < i; j++)
len[j] += wi;
if (tmp) len[i] += wi;//如果进了while循环就跟for循环做的处理一样
else len[i] = wi;//如果没进循环,就直接就是自己的长度
h[i++] = hi;
}
while(i > 0) {
i--;
res = max(res, h[i]*len[i]);
}
printf("%I64d\n", res);
}
return 0;
}
总结:用数组可以对所有元素都进行处理,而栈只可以对栈顶元素处理,不知道用栈干什么0.0!
例题 :队列 poj 2259 Team Queue
题意:就像要排一只很长的队伍,但是不想从最后面排起,于是就会从头到尾看看队伍中有没有熟人在,如果有,就插队到熟人后面;如果没有,就只能从队尾慢慢排了。输入一开始是说明哪些人是一组的,后面才是入队与出队的操作;(一开始没看懂题目,没搞懂输入,一下顿悟了);
发两个:
1用库函数做的:
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
using namespace std;
int nCaseNum, nNum;
queue<long> nQue[1001]; //储存每个队列
queue<int> nS; //储存队列号
int nM[1000000]; //元素与队列号的映射表
bool nFlag[1001]; //标识有无同组元素
void solve() {
string nCommand;
long nElem;
cout<<"Scenario #"<<++nCaseNum<<endl;
while(cin>>nCommand, nCommand != "STOP") {
if (nCommand == "ENQUEUE") {
cin>>nElem;
if(!nFlag[nM[nElem]]) { //若还没有同组元素
nFlag[nM[nElem]] = true;
nS.push(nM[nElem]); //将组号进队列
}
nQue[nM[nElem]].push(nElem);
}else if (nCommand == "DEQUEUE") {
int nId = nS.front(); //首先处理最先进队列的那组元素
cout<<nQue[nId].front()<<endl;
nQue[nId].pop();
if (nQue[nId].empty()) {
nS.pop();
nFlag[nId] = false;
}
}
}
cout<<endl;
}
void init() {//初始化很重要
for(int i = 0; i != nNum; ++i) {
nFlag[i] = false;
while(!nQue[i].empty()) nQue[i].pop();
}
while(!nS.empty()) nS.pop();
}
void input() {
int nElem, elemNum;
for(int i = 0; i != nNum; ++i) {
cin>>elemNum;
for(int j = 0; j != elemNum; ++j) {
cin>>nElem;
nM[nElem] = i;
}
}
}
int main() {
nCaseNum = 0;
while(cin>>nNum, nNum) {
init();
input();
solve();
}
return 0;
}
内存 1600k 时间 900ms
2 用结构体:
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 1000000;
const int ele = 1008;
char c[16];
struct que { //队列的结构体
int l, r;
int st[ele];
}que1, queplus[ele];
int a[maxn];//元素与队列号的映射表
int main() {
int n, t, x, i, j, k = 1;
while(scanf("%d", &n) && n) {
que1.l = que1.r = 0; //初始化很重要
for(i = 0; i < ele; i++)
queplus[i].l = queplus[i].r = 0;
printf("Scenario #%d\n", k++); //忘记++;
i = 0;
while(n--) {
scanf("%d", &t);
while(t--) {
scanf("%d", &x);
a[x] = i;
}
i++;
}
while(scanf("%s", c) && strcmp(c, "STOP")) {
if (!strcmp(c, "ENQUEUE")) {
scanf("%d", &x);
j = a[x];
if (queplus[j].l == queplus[j].r) //队列为空就说明x是第一个
que1.st[que1.r++] = j;
queplus[j].st[queplus[j].r++] = x;
}
else{
j = que1.st[que1.l];
printf("%d\n", queplus[j].st[queplus[j].l++]);
if (queplus[j].l == queplus[j].r) //这组出所有元素出完后,大队列首元素出队列
que1.l++;
}
}
printf("\n");
}
return 0;
}
wa了很多次,总结不要小看输入的这些操作,主要细心;
内存4800k 时间 270ms
比较:用数组的节构体时间快很多,还有很多操作是库函数没有的;但用库函数写起来比较简洁0.0。