acm新手小白必看系列之(10)——队列精讲及例题
队列其实是很复杂的,有很多种队列的情况
下面只讲基础能用上的
队列:先进先出
在这里,我将引入两个整型变量head和tail。head用来记录队列的队首(即第一位),tail用来记录队列的队尾(即最后一位)的下一个位置。你可能会问:为什么tail不直接记录队尾,却要记录队尾的下一个位置呢?这是因为当队列中只剩下一个元素时,队首和队尾重合会带来一些麻烦。我们这里规定队首和队尾重合时,队列为空
如果现在有9个数,9个数全部放入队列之后head=1;tail=10;此时head和tail之间的数就是目前队列中“有效”的数。如果要删除一个数的话,就将head++就OK了,这样仍然可以保持head和tail之间的数为目前队列中“有效”的数。这样做虽然浪费了一个空间,却节省了大量的时间,这是非常划算的。新增加一个数也很简单,把需要增加的数放到队尾即q[tail]之后再tail++就OK啦。
我们来小结一下,在队首删除一个数的操作是head++;
在队尾增加一个数(假设这个数是x)的操作是q[tail]=x;tail++;。
队列将是我们今后学习广度优先搜索以及队列优化的Bellman-Ford最短路算法的核心数据结构。所以现在将队列的三个基本元素(一个数组,两个变量)封装为一个结构体类型,如下
struct queue
{
int data[100];//队列的主体,用来存储内容
int head;//队首
int tail;//队尾};
}
- 简单队列很简单下面来实践一下
- 1.解密
解密规则。规则是这样的:首先将第1个数删除,紧接着将第2个数放到这串数的末尾,再将第3个数删除并将第4个数放到这串数的末尾,再将第5个数删除…直到剩下最后一个数,将最后一个数也删除。按照刚才删除的顺序,把这些删除的数连在一起即为正确数列
输入 6 3 1 7 5 8 9 2 4
输出 6 1 5 9 4 7 2 8 3
#include <stdio.h>
int main()
{
int q[102]={0,6,3,1,7,5,8,9,2,4},head,tail;
int i;
//初始化队列
head=1;
tail=10; //队列中已经有9个元素了,tail执向的队尾的后一个位置
while(head<tail) //当队列不为空的时候执行循环
{
//打印队首并将队首出队
printf("%d ",q[head]);
head++;
//先将新队首的数添加到队尾
q[tail]=q[head];
tail++;
//再将队首出队
head++;
}
getchar();getchar();
return 0;
}
即将推出acm新手进阶必看系列(1)——链表精讲即例题
往期回顾
1.溶液配制
小蓝虽然有很多溶液,但是还是没有办法配成想要的溶液,因为万一倒错了就没有办法挽回了。因此,小蓝到网上下载了一个溶液配置模拟器。模拟器在计算机中构造一种虚拟溶液,然后可以虚拟地向当前虚拟溶液中加入一定浓度、一定体积的这种溶液,模拟器会快速地算出倒入后虚拟溶液的浓度和体积。当然,如果倒错了可以撤销。
模拟器的使用步骤如下:
1)为模拟器设置一个初始体积和浓度 V0、C0%。
2)进行一系列操作,模拟器支持两种操作:
P(v,c)操作:表示向当前的虚拟溶液中加入体积为 v 浓度为 c 的溶液;
Z 操作:撤销上一步的 P 操作。
Input
第一行两个整数,表示 V0 和 C0,0≤C0≤100;
第二行一个整数 n,表示操作数,n≤10000;
接下来 n 行,每行一条操作,格式为:P_v_c 或 Z。
其中 _ 代表一个空格,当只剩初始溶液的时候,再撤销就没有用了,这时只输出初始的体积和浓度。
任意时刻质量不会超过 2^31 -1。
Output
n 行,每行两个数 Vi,Ci,其中 Vi 为整数,Ci 为实数(保留 5 位小数)。
其中,第 i 行表示第 i 次操作以后的溶液体积和浓度。
Sample Input
100 100
2
P 100 0
Z
Sample Output
200 50.00000
100 100.00000
Hint
例子输入2:
100 100
2
Z
P 100 0
例子输出2:
100 100.00000
200 50.00000
//当只剩初始溶液的时候,再撤销就没有用了,这时只输出初始的体积和浓度。
//注意这句话! 用栈模拟很方便的
#include <bits/stdc++.h>
using namespace std;
struct sa
{
int v;
double c;
};
stack<sa>vis;
int main()
{ ios::sync_with_stdio(false);
string p;
int v0,n,v1,v10,v20;
double c0,c1,c10,c20;
cin>>v0>>c0;
v20=v0;
c20=c0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>p;
if (p=="P")
{
cin>>v1>>c1;
vis.push({v1,c1});
c0=(v0*c0*0.01+v1*c1*0.01)/(v0+v1);
c0=c0*100.00;
v0=v0+v1;
printf("%d %.5lf\n",v0,c0);
}
else
{
if (vis.empty())
{
printf("%d %.5lf\n",v20,c20);
continue;
}
sa tmp=vis.top();
vis.pop();
v10=tmp.v;
c10=tmp.c;
c0=((v0*c0*0.01-v10*c10*0.01)/(v0-v10))*100.00;
v0=v0-v10;
printf("%d %.5lf\n",v0,c0);
}
}
return 0;
}
好了,acm新手系列完结撒花O(∩_∩)O~
即将推出acm新手进阶必看系列(1)——链表精讲即例题