队列
基本概念
nefu 1632-周末舞会
思路:由于两个人一一对应,想到用两个队列存储对应输出即可
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
int m,f,n;
queue<int>vis1;//存放男生编号
queue<int>vis2;//存放女生编号
cin>>m>>f>>n;//m男生数,f为女生数,n为舞曲数
for(int i=1;i<=m;i++)
vis1.push(i);
for(int i=1;i<=f;i++)
vis2.push(i);
for(int i=1;i<=n;i++)
{
int s1=vis1.front();//s1存放对首男生
vis1.pop();//组队之后出去
int s2=vis2.front();//s1存放对首女生
vis2.pop();
printf("%d %d\n",s1,s2);
vis1.push(s1);//出去之后进入队尾
vis2.push(s2);
}
return 0;
}
nefu 1634 报数-队列-约瑟夫环
思路:让前d个小朋友不断到队尾,排出第d个小朋友,直到队伍中只有一个小朋友
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N=1e5;
int main()
{
int n,d,t,ans;//n个小朋友,第d个小朋友离开
queue<int>vis;//将所有小朋友排好
cin>>n>>d;
for(int i=1; i<=n; i++)
vis.push(i);
while(vis.size()!=1)//直到只剩下一个小朋友
{
for(int i=1;i<=d-1;i++)//让前d个小朋友排到队尾
{
ans=vis.front();
vis.pop();
vis.push(ans);
}
vis.pop();
}
printf("%d",vis.front());
return 0;
}
nefu 1635 酒桌游戏-队列
思路:
确定开始报数的位置,再判断是否符合条件将其排出或者排到队尾
由于数字和名字是想关联的,需要使用结构体
step1:写一个函数判断其是否符合所需条件
step2:将开始报数的人放到队首
step3:应用上面写的函数判断其是否符合条件,先用node tmp=vis.top()记录队首,再进行判断,符合则直接排出,不符合,放回队尾
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct node{
int num;
string name;
}p[10001];
bool judge(int x)//判断此人是否出局
{
if(x%7==0) return 1;
while(x)
{
if(x%10==7) return 1;
x=x/10;
}
return 0;
}
queue<node>vis;
int main()
{
int m,n,t;//t表示开始报数的人报出的数字是t
//n代表人数,m代表开始报数的人的编号
string name;
cin>>n>>m>>t;
for(int i=1;i<=n;i++)
{
cin>>p[i].name;
p[i].num=i;
}
for(int i=1;i<=n;i++)
vis.push(p[i]);//把队列中的每个数据都输入
for(int i=1;i<m;i++)//调整顺序,队首的人开始报数
{
vis.push(p[i]);
vis.pop();
}
while(vis.size()!=1)
{
node tmp=vis.front();
vis.pop();//把队首拿出去
if(judge(t)==0) vis.push(tmp);
//如果对首不符合,再将其放到队尾
t++;
}
printf("%s\n",vis.front().name.c_str());
return 0;
}
nefu 1663 关系网络-队列
思路:
从第x行下手,如果a[x][j]=1,a[j][y]=1,那么x能通过关系认识y,此时从j列换为j行,循环每一列,将新认识的人变为1
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int a[101][101],b[101];
//将矩阵存入二维数组
int main()
{
int n,x,y,i,j,m;
while(cin>>n>>x>>y)//n维矩阵,x认识y的途径
{
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
cin>>a[i][j];
//正常将矩阵输入
//当a[x][y]==1时x直接就能认识y了,所以讨论以下情形
if(a[x][y]==0)
{
for(i=1; i<=n; i++) //控制几步
{
for(j=1; j<=n; j++) //循环每一列
{
if(a[x][j]==1)
b[j]=1; //如果该行存在1,那么先用数组标记上
}
for(j=1; j<=n; j++) //将获取到的列数换位行,可连接传递
{
if(b[j]==1)//如果能取到该列,就能传递到该行
{
for(m=1; m<=n; m++)//循环新的一行的每列
{
if(a[j][m]==1)
a[x][m]=1;//当第x行能取到y列时,x就能认识y
}
}
}
if(a[x][y]==1)
break;
}
}
else i=0;
printf("%d\n",i);
}
return 0;
}
nefu 1636 海港-队列
思路:
此题要将结构体按人来定义,因为需要用到每个人的国籍数。判断一个人的国籍是否出现过,使用桶排,a[国籍]==0时,表示其出现一次则让该国籍人数:a[国籍]++,国籍数ans++。当最后一个人比队首入港时间大于24小时时,a[国籍]–;直到a[国籍]==0,此时国籍总数-1
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct human
{
int time;
int race;
};
int a[3000000];//记录所有人的国籍,每个人对应数组的一项
queue<human>vis;
int main()
{
int n,k,t,ans=0,x;//n组数据,t为到达时间,k为人数
//ans记录总的国籍数,x记录输入时每个人的国籍
struct human tmp;//tmp用来记录队首
cin>>n;
while(n--)
{
cin>>t>>k;
for(int i=1; i<=k; i++)
{
cin>>x;
vis.push({t,x});//把所有人的数据压入队列
if(a[x]==0)
ans++;
a[x]++;
}//利用桶排,当开始a[x]==0时即多一个国籍数
while(t-vis.front().time>=86400)//当时间超出24小时
{//逐渐将最开始的人所在的国籍删除,当记录该国籍的那项变为0,相应总数-1
tmp=vis.front();
vis.pop();
int s1=tmp.race;
a[s1]--;
if(a[s1]==0)
ans--;
}
printf("%d\n",ans);
}
return 0;
}
nefu 1662 Blash数集-队列-set
思路:
与丑数一样,所有的数均由开始的数变化而来,每次取其中最小的即可保证所有的blash数都能取到。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int a[100000+1];
int main()
{
int p2,n,p3;
cin>>a[1]>>n;
p2=1;
p3=1;
for(int i=2;i<=n;i++)
{
a[i]=min(2*a[p2]+1,3*a[p3]+1);
if(a[i]==2*a[p2]+1) p2++;
if(a[i]==3*a[p3]+1) p3++;
}
printf("%d",a[n]);
return 0;
}