【宽度优先搜索/BFS/队列】[11.13]

P1996 约瑟夫问题

n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号.

队列做法:
1.依次全部编号
2.用一个变量now作为报数:若now!=m,把这一个丢到队尾(先push队首,再pop),下一个继续报数。这样一来实际上将圆圈转化为线性,报过了的可以在最后重新按原来的顺序报;若now==m,丢出去,记编号,now=1,下一个从1开始报。

#include<cstdio>
#include<queue>
using namespace std;
int main()
{
	queue<int>q;
	int n,m,now=1;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) q.push(i);
	while(!q.empty()){
		if(now==m) {printf("%d ",q.front());q.pop();now=1;}
		else{now++;q.push(q.front());q.pop();}
	}
	return 0;
 } 

P1443 马的遍历

//以点为单位进行队列操作时的队列声明
queue< pair<int,int> > Q;
//临时创建一个点pair
make_pair(x,y);

//取用队列第一个元素的x值与y值
Q.front().first;
Q.front().second;
//左对齐,宽五格(实际间隔为4)
printf("%-5d",a);
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
//马走日字
//不用for循环,写八个bfs也行……
int dx[10]={0,-1,-1,-2,-2,1,1,2,2};
int dy[10]={0,2,-2,1,-1,2,-2,1,-1};
int n,m,sx,sy;
int map[410][410];
queue< pair<int,int> > Q;

int main()
{
	scanf("%d%d%d%d",&n,&m,&sx,&sy);
	memset(map,-1,sizeof(map));
	map[sx][sy]=0;
	Q.push(make_pair(sx,sy));
	while(!Q.empty()){
		int x=Q.front().first,y=Q.front().second;
		for(int i=1;i<=8;i++){
			int nx=x+dx[i],ny=y+dy[i];
			if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&map[nx][ny]==-1){
				map[nx][ny]=map[x][y]+1;
				Q.push(make_pair(nx,ny));
			}
		}
		Q.pop();//用完当前的点就踹掉
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			printf("%-5d",map[i][j]);
		}
		printf("\n");
	}
	return 0;
 } 

SP348 EXPEDI - Expedition

白书上priority queue的一道题,竟然是紫色的……
本身是道贪心题,不过大概难在思考方向:将在加油站加油看作“经过加油站 i 时即获得在此之后的任意时刻加 Bi 单位汽油的资格”,也就是说,在油用完之前一口气跑过所有加油站,每个加油站领个云加油的汽油券,都储存在优先队列中,在油不够跑到下一个加油站的时候,再把汽油券拿出来挑个最大的(这也是优先队列的特性,取的是队列中的最大值),云加油一次,再接着跑。

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
struct stop{
	int a,b;
}s[10005];

bool cmp(stop a,stop b){
	return a.a<b.a;
}

int main()
{
	int t;
	scanf("%d",&t);
	while(t--){
		memset(s,0,sizeof(s));
		int n,l,p;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) {scanf("%d%d",&s[i].a,&s[i].b);}
		scanf("%d%d",&l,&p);
		for(int i=1;i<=n;i++) {s[i].a=l-s[i].a;}
		s[n+1].a=l;
		s[n+1].b=0;
		sort(s+1,s+n+2,cmp);
		priority_queue<int>que;
		int ans=0,pos=0,tank=p,ok=1;
		for(int i=1;i<=n+1;i++){
			int d=s[i].a-pos;
			while(tank-d<0){
				if(que.empty()){
					ok=0;
					break;
				}
				tank+=que.top();
				que.pop();
				ans++;
			}
			if(ok==0) break;
			tank-=d;
			pos=s[i].a;
			que.push(s[i].b);
		}
		if(ok==0) printf("-1\n");
		else printf("%d\n",ans);
	}
	return 0;
 }

UVA540 团体队列

#include<stdio.h>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;

int main()
{
	int kase=0;
	int t;
	while(scanf("%d",&t)==1&&t){
	printf("Scenario #%d\n",++kase);
	map<int,int> team;
	//将每个队员具体编号对应至所属队伍的编号
	for(int i=1;i<=t;i++){
		int n,x;
		scanf("%d",&n);
		while(n--){
		scanf("%d",&x);
		team[x]=i;
		}
	}
	queue<int>q,q2[1010];
	//队列q用于储存每一个队伍的编号,q2[i]用于储存队伍i里每个成员的编号 
	for(;;){
		int num;
		char cmd[10];
		scanf("%s",cmd);
		if(cmd[0]=='S') break;
		if(cmd[0]=='E') {
			scanf("%d",&num);
			if(q2[team[num]].empty()) q.push(team[num]);
			//如果没有队友,就创建他所属的队伍,丢到长队的末尾 
			q2[team[num]].push(num);
			//将编号为num的人丢到它所属的队伍的末尾 
		}
		if(cmd[0]=='D'){
			int t=q.front();
			//取长队里第一个队伍的编号 
			printf("%d\n",q2[t].front());q2[t].pop();
			//取第一个队伍里第一个人的编号,输出,然后丢出去 
			if(q2[t].empty()) q.pop();
			//如果丢出了队伍的最后一个人,那么丢出这个队伍编号 
		}	
	}
	printf("\n");
	}
	return 0;
} 
发布了28 篇原创文章 · 获赞 0 · 访问量 679

猜你喜欢

转载自blog.csdn.net/weixin_45561591/article/details/102757192
今日推荐