一、连续区域矩形面积(栈)
题目概述
Sample Input
3 1 2 3 4 1 2 3 3 4 1 2 3 4 -1 Sample Output12 14 题目大意:给出一系列矩形的宽度和高度,矩形沿着x轴对齐,求这些矩形组成的连续矩形区域的最大面积。 解题方法:这是一道非常好的题,用栈保存矩形,如果高度递增则不断入栈,如果遇到当前输入的比栈顶高度小,则从栈顶开始不断出栈并且计算最大面积,直到栈顶高度小于当前输入高度则停止出栈,并把开始出栈矩形的宽度累加得到totalw,把totalw和当前输入的矩形宽度相加得到当前输入矩形的宽度,并入栈,这样栈中保存的永远都是高度递增的矩形,最后输入完了之后如果栈不为空,则依次出栈并计算最大面积。(ACM题目原型(POJ2082))
#include <bits/stdc++.h>
using namespace std;
int n,maxS=0;
typedef struct{
int w,h;
}rec;
int main() {
stack<rec> s;
while(scanf("%d", &n) != EOF && n != -1)
{
int w,h,totalW;
maxS=0;
for(int i=0;i<n;i++)
{
cin>>w>>h;
if(s.empty()) //如果栈为空 表明第一次有矩形输入 直接入栈
{
rec t;
t.w=w;
t.h=h;
s.push(t);
}
else //栈里已经有值 判断决定出栈计算值 or 入栈
{
totalW=0;
//注意出栈后一定要判断空 不然程序可能会死循环
while(!s.empty()&&s.top().h>h) //栈顶矩形的高度大于新矩形的高度 出栈
{
totalW+=s.top().w;
if(totalW*s.top().h>maxS)
maxS=totalW*s.top().h;
s.pop();
}
//执行下面的语句时两种情况: totalW已经更新过需要新矩形入栈 or totalW仍然为0新矩形需要入栈
totalW+=w;
rec t;
t.w=totalW;
t.h=h;
s.push(t);
}
}
totalW=0; //下面这种情况属于矩形的高度始终递增 则还没有计算过最大面积 需清除totalW 重新计算
while(!s.empty())
{
rec t=s.top();
totalW+=t.w;
if(t.h*totalW>maxS)
maxS=t.h*totalW;
s.pop();
}
cout<<maxS<<endl;
}
return 0;
}
二、模拟插队
题目概述:
Sample input
2 3 101 102 103 3 201 202 203 ENQUEUE 101 ENQUEUE 201 ENQUEUE 102 ENQUEUE 202 ENQUEUE 103 ENQUEUE 203 DEQUEUE DEQUEUE DEQUEUE DEQUEUE DEQUEUE DEQUEUE STOP 2 5 259001 259002 259003 259004 259005 6 260001 260002 260003 260004 260005 260006 ENQUEUE 259001 ENQUEUE 260001 ENQUEUE 259002 ENQUEUE 259003 ENQUEUE 259004 ENQUEUE 259005 DEQUEUE DEQUEUE ENQUEUE 260002 ENQUEUE 260003 DEQUEUE DEQUEUE DEQUEUE DEQUEUE STOP 0Sample output
Scenario #1 101 102 103 201 202 203 Scenario #2 259001 259002 259003 259004 259005 260001大概题意:类似于学校排队打饭,模拟这过程,只有队伍中有你们班的人你才可以插队,不然你只能排在队尾。ENQUEUE x,代表编号为x的人来排队,DEQUEUE时表明队伍最前面的人出队列,STOP时停止。
执行思路:详见代码,大概是,用一个队列数组来表明那个班的人员所有编号,一个队列来模拟当前的班级排队情况,牵涉到很多标记数组,如:用一个数组映射人员编号和队伍,一个数组标记在排队的班级号,剩下的直接模拟队列就好。(Uva 540 - Team Queue)
#include <bits/stdc++.h>
using namespace std;
/*
需要申明的变量:
数组队列nQueue:用以存储每个队有哪些人
标记队列nS:标识在排队的队伍号
标记数组nFlag:标识在排队的队伍号
标记数组nM:标记每一个队员的队号 如:nM[1001]=1
*/
queue<long> nQueue[1001]; //最多每个队伍只有1001个人
queue<int> nS;
int nM[1000000],nCaseNum = 0,nNum; //人总数不超过1000000,nCaseNum为第几次模拟排队,nNum为本轮的队伍数
bool nFlag[1001]; //每个队伍是否在队列中的标志
void initQueue();
void queueInput();
void queueStimulate();
int main() {
while(scanf("%d",&nNum)!=EOF&&nNum!=0)
{
initQueue();
queueInput();
queueStimulate();
}
}
void initQueue()
{
for (int i = 0; i != nNum; ++i)
{
nFlag[i]=false;
while(!nQueue[i].empty()) //每个队伍清空
nQueue[i].pop();
}
while(!nS.empty()) nS.pop(); //标志队列清空
}
void queueInput()
{
long nElem,elemNum; //elemNum代表每个队伍的人数 nElem代表每个队伍的人的编号
for(int i=0;i!=nNum;++i)
{
cin>>elemNum;
for(int j=0;j!=elemNum;++j)
{
cin>>nElem;
nM[nElem]=i; //记录每个人的队伍号
}
}
}
void queueStimulate()
{
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]);
}
nQueue[nM[nElem]].push(nElem); //把这个人放进对应的队伍中
}
else if(nCommand=="DEQUEUE") //出队列
{
int nID=nS.front();
cout<<nQueue[nID].front()<<endl; //输出在队首的人员编号并弹出
nQueue[nID].pop();
//处理弹出操作后带来的标识位变化
if(nQueue[nID].empty())
{
nS.pop();
nFlag[nID]=false;
}
}
}
cout<<endl;
}