第五次双周赛

L1-1 计算摄氏温度

本题要求编写程序,计算华氏温度100°F对应的摄氏温度。计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型。

输入格式:

本题目没有输入。

输出格式:

按照下列格式输出

fahr = 100, celsius = 计算所得摄氏温度的整数值

代码长度限制                                                                        16 KB

时间限制                                                                                400 ms

内存限制                                                                                64 MB

思路:

        签到题,计算后输出。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long int

int main()
{
	int f=100;
	int c=5*(f-32)/9;
	printf("fahr = 100, celsius = %d",c);
	return 0;
}

L1-2 查验身份证

一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:

首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z;最后按照以下关系对应Z值与校验码M的值:

Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2

现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。

输入格式:

输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。

输出格式:

按照输入的顺序每行输出1个有问题的身份证号码。这里并不检验前17位是否合理,只检查前17位是否全为数字且最后1位校验码计算准确。如果所有号码都正常,则输出All passed

输入样例1:

4
320124198808240056
12010X198901011234
110108196711301866
37070419881216001X

输出样例1:

12010X198901011234
110108196711301866
37070419881216001X

输入样例2:

2
320124198808240056
110108196711301862

输出样例2:

All passed

代码长度限制                                                                        16 KB

时间限制                                                                                400 ms

内存限制                                                                                64 MB

思路:

        按题目模拟。注意加权总和是100,不要化为小数。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int k[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char m[11]={'1','0','X','9','8','7','6','5','4','3','2'};
char a[20];
int main()
{
	std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    int cnt=0;
    int n;cin>>n;
    for(int i=1;i<=n;++i)
    {
    	cin>>a;
    	int sum=0;
    	bool f=true;
    	for(int j=0;j<=16;++j)
    	{
    		if(a[j]<='9'&&a[j]>='0')
    		{
    			int b=a[j]-'0';
    			sum+=k[j]*b;
			}
			else
			{
				f=false;
			}
		}
		if(!f)
		{
			++cnt;
			cout<<a<<'\n';
			continue;
		}
		sum=(sum)%11;
		if(a[17]!=m[sum])
		{
			++cnt;
			cout<<a<<'\n';
		}	
	}
	if(cnt==0) cout<<"All passed"<<'\n';
	return 0;
}

L1-3 帅到没朋友

当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友。本题就要求你找出那些帅到没有朋友的人。

输入格式:

输入第一行给出一个正整数N(≤100),是已知朋友圈的个数;随后N行,每行首先给出一个正整数K(≤1000),为朋友圈中的人数,然后列出一个朋友圈内的所有人——为方便起见,每人对应一个ID号,为5位数字(从00000到99999),ID间以空格分隔;之后给出一个正整数M(≤10000),为待查询的人数;随后一行中列出M个待查询的ID,以空格分隔。

注意:没有朋友的人可以是根本没安装“朋友圈”,也可以是只有自己一个人在朋友圈的人。虽然有个别自恋狂会自己把自己反复加进朋友圈,但题目保证所有K超过1的朋友圈里都至少有2个不同的人。

输出格式:

按输入的顺序输出那些帅到没朋友的人。ID间用1个空格分隔,行的首尾不得有多余空格。如果没有人太帅,则输出No one is handsome

注意:同一个人可以被查询多次,但只输出一次。

输入样例1:

3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
8
55555 44444 10000 88888 22222 11111 23333 88888

输出样例1:

10000 88888 23333

输入样例2:

3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
4
55555 44444 22222 11111

输出样例2:

No one is handsome

代码长度限制                                                                        16 KB

时间限制                                                                                300 ms

内存限制                                                                                64 MB

思路:

        把各个朋友圈提到的全部标记,统计人数,最后输出。注意每个人的编号是5位数,不足五位的前补0输出。

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int vis[200010];
int v[200010];
int ans[200010];
int main()
{
	int n;scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		int k;scanf("%d",&k);
		for(int j=1;j<=k;++j)
		{
			int id;scanf("%d",&id);
			if(k!=1) vis[id]=1;
		}
	}
	int cnt=0;
	int m;scanf("%d",&m);
	for(int i=1;i<=m;++i)
	{
		int a;scanf("%d",&a);
		if(vis[a]==0&&v[a]==0)
		{
			v[a]=1;
			ans[++cnt]=a;
		}
	}
	if(cnt==0) printf("No one is handsome");
	else
	{
		for(int i=1;i<=cnt;++i)
		{
			printf("%05d",ans[i]);
			if(i<cnt) printf(" ");
		}
	}
	printf("\n");
	return 0;
}

L1-4 输出GPLT

给定一个长度不超过10000的、仅由英文字母构成的字符串。请将字符重新调整顺序,按GPLTGPLT....这样的顺序输出,并忽略其它字符。当然,四种字符(不区分大小写)的个数不一定是一样多的,若某种字符已经输出完,则余下的字符仍按GPLT的顺序打印,直到所有字符都被输出。

输入格式:

输入在一行中给出一个长度不超过10000的、仅由英文字母构成的非空字符串。

输出格式:

在一行中按题目要求输出排序后的字符串。题目保证输出非空。

输入样例:

pcTclnGloRgLrtLhgljkLhGFauPewSKgt

输出样例:

GPLTGPLTGLTGLGLL

代码长度限制                                                                        16 KB

时间限制                                                                                200 ms

内存限制                                                                                64 MB

思路:

        统计四种字母各有多少个,输出时遇到不够的跳过,直到全部输出完。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
char a[10010];
int cnt[4];
char c[4]={'G','P','L','T'};
int main()
{
	std::ios::sync_with_stdio(false);
    std::cin.tie(0);
	cin>>a;
	for(int i=0;i<strlen(a);++i)
	{
		if(a[i]=='G'||a[i]=='g') ++cnt[0];
		if(a[i]=='P'||a[i]=='p') ++cnt[1];
		if(a[i]=='L'||a[i]=='l') ++cnt[2];
		if(a[i]=='T'||a[i]=='t') ++cnt[3];
	}
	int k=0;
	while(cnt[0]||cnt[1]||cnt[2]||cnt[3])
	{
		if(cnt[k])
		{
			cout<<c[k];--cnt[k];
		}
		++k;k%=4;
	}
	return 0;
}

L1-5 判断素数

本题的目标很简单,就是判断一个给定的正整数是否素数。

输入格式:

输入在第一行给出一个正整数N(≤ 10),随后N行,每行给出一个小于231的需要判断的正整数。

输出格式:

对每个需要判断的正整数,如果它是素数,则在一行中输出Yes,否则输出No

输入样例:

2
11
111

输出样例:

Yes
No

代码长度限制                                                                        16 KB

时间限制                                                                                400 ms

内存限制                                                                                64 MB

思路:

        试除法即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
void ch(ll k)
{
	for(int i=2;i<=sqrt(k);++i)
	{
		if(k%i==0)
		{
			cout<<"No"<<'\n';return;
		}
	}
	cout<<"Yes"<<'\n';
}
int main()
{
	std::ios::sync_with_stdio(false);
    std::cin.tie(0);
	int n;cin>>n;
	for(int i=1;i<=n;++i)
	{
		ll k;cin>>k;
		if(k<=1)
		{
			printf("No\n");
			continue;
		}
		ch(k);
	}
	return 0;
}

L1-6 最佳情侣身高差

专家通过多组情侣研究数据发现,最佳的情侣身高差遵循着一个公式:(女方的身高)×1.09 =(男方的身高)。如果符合,你俩的身高差不管是牵手、拥抱、接吻,都是最和谐的差度。

下面就请你写个程序,为任意一位用户计算他/她的情侣的最佳身高。

输入格式:

输入第一行给出正整数N(≤10),为前来查询的用户数。随后N行,每行按照“性别 身高”的格式给出前来查询的用户的性别和身高,其中“性别”为“F”表示女性、“M”表示男性;“身高”为区间 [1.0, 3.0] 之间的实数。

输出格式:

对每一个查询,在一行中为该用户计算出其情侣的最佳身高,保留小数点后2位。

输入样例:

2
M 1.75
F 1.8

输出样例:

1.61
1.96

代码长度限制                                                                        16 KB

时间限制                                                                                400 ms

内存限制                                                                                64 MB

思路:

        判断男女,选择对应的计算方式后输出。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int main()
{
	int n;scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		getchar();
		char f;scanf("%c",&f);
		double h;scanf("%lf",&h);
		if(f=='M') printf("%.2lf\n",h/1.09);
		else printf("%.2lf\n",h*1.09);
	}
	return 0;
}

L1-7 连续因子

一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。

输入格式:

输入在一行中给出一个正整数 N(1<N<231)。

输出格式:

首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1*因子2*……*因子k 的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。

输入样例:

630

输出样例:

3
5*6*7

鸣谢用户 漏穿雪 补充数据!

代码长度限制                                                                        16 KB

时间限制                                                                                400 ms

内存限制                                                                                64 MB

思路:

        从 1 到sqrt(n)遇到能整除的就试一试连续因子,统计长度,与之前的比较,如果更长则更新长度和开始的因数。最后输出。

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
//	std::ios::sync_with_stdio(false);
//	std::cin.tie(nullptr);
//	std::cout.tie(nullptr);
	int n=0;
	scanf("%d",&n);
	int temp=0,ans=0;
	int x=sqrt(n);
	for(int i=2;i<=x;++i)
	{
		int num=0;
		int sum=n;
		int res=i;
		for (int j=i;sum%j==0&&sum!=0;++j)
		{
			sum/=j;
			num++;
		}
		if (num>temp)
		{
			temp=num;//筛选最长因子个数
			ans=res;
		}
	}
	if(temp==0)
		printf("1\n%d",n);
	else
	{
		printf("%d\n",temp);
		int k=ans;
		while(k<ans+temp)
		{
			if(k!=ans)
				printf("*");
			printf("%d",k);
			k++;
		}
	}
	return 0;
}

L1-8 出生年

以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才遇到4个数字都不相同的年份。”也就是说,直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求,自动填充“我出生于y年,直到x岁才遇到n个数字都不相同的年份”这句话。

输入格式:

输入在一行中给出出生年份y和目标年份中不同数字的个数n,其中y在[1, 3000]之间,n可以是2、或3、或4。注意不足4位的年份要在前面补零,例如公元1年被认为是0001年,有2个不同的数字0和1。

输出格式:

根据输入,输出x和能达到要求的年份。数字间以1个空格分隔,行首尾不得有多余空格。年份要按4位输出。注意:所谓“n个数字都不相同”是指不同的数字正好是n个。如“2013”被视为满足“4位数字都不同”的条件,但不被视为满足2位或3位数字不同的条件。

输入样例1:

1988 4

输出样例1:

25 2013

输入样例2:

1 2

输出样例2:

0 0001

代码长度限制                                                                                16 KB

时间限制                                                                                        400 ms

内存限制                                                                                        64 MB

 思路:

        一年一年地判断,直到找到符合题目的年份。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int vis[10];
int main()
{
	int y,n;
	scanf("%d%d",&y,&n);
	int cnt=0;
	while(y<=10000)
	{
		memset(vis,0,sizeof(vis));
		int k=y;
		while(k)
		{
			vis[k%10]=1;
			k/=10;
		}
		if(y<1000) vis[0]=1;
		int num=0;
		for(int i=0;i<=9;++i)
		{
			if(vis[i]) ++num; 
		}
		if(num==n)
		{
			printf("%d %04d",cnt,y);
			break;
		}
		cnt++;y++;
	}
	return 0;
}

/*



*/

L2-1 红色警报

战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。

输入格式:

输入在第一行给出两个整数N(0 < N ≤ 500)和M(≤ 5000),分别为城市个数(于是默认城市从0到N-1编号)和连接两城市的通路条数。随后M行,每行给出一条通路所连接的两个城市的编号,其间以1个空格分隔。在城市信息之后给出被攻占的信息,即一个正整数K和随后的K个被攻占的城市的编号。

注意:输入保证给出的被攻占的城市编号都是合法的且无重复,但并不保证给出的通路没有重复。

输出格式:

对每个被攻占的城市,如果它会改变整个国家的连通性,则输出Red Alert: City k is lost!,其中k是该城市的编号;否则只输出City k is lost.即可。如果该国失去了最后一个城市,则增加一行输出Game Over.

输入样例:

5 4
0 1
1 3
3 0
0 4
5
1 2 0 4 3

输出样例:

City 1 is lost.
City 2 is lost.
Red Alert: City 0 is lost!
City 4 is lost.
City 3 is lost.
Game Over.

代码长度限制                                                                        16 KB

时间限制                                                                                400 ms

内存限制                                                                                64 MB

思路:

        用并查集判断是否联通。

        先统计一次联通的情况,记录连通块个数。后每被攻下一座城市,重新统计联通情况,并与之前的比较,以此判断输出。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int per[N],rnk[N];
int find(int x)
{
	if(per[x]==x) return x;
	else return per[x]=find(per[x]);
}
void unite(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x==y)//同一集合
		return;
	if(rnk[x]<rnk[y]) per[x]=y;
	else
	{
		per[y]=x;
		if(rnk[y]==rnk[x])
			rnk[x]++;
	}
}
int lost[N];
pair<int,int> road[N];
void init(int n)
{
	for(int i=0;i<=n;++i) per[i]=i;
}
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cin.tie(nullptr);
	int n,m;cin>>n>>m;
	init(n);
	for(int i=0;i<m;++i)
	{
		int x,y;cin>>x>>y;
		unite(x,y);//二者联通 
		road[i].first=x;
		road[i].second=y;
	}
	int cnt0=0;//联通块数量 
	for(int i=0;i<n;++i)
		if(per[i]==i) cnt0++;
	int lostnum=0;
	int k;cin>>k;
	for(int i=0;i<k;++i)
	{
		int x;cin>>x;
		init(n);//清空,重新统计 
		lost[x]=1;
		lostnum++;
		for(int i=0;i<m;++i)
		{
			if(lost[road[i].first]||lost[road[i].second])
				continue;//此路不通 
			unite(road[i].first,road[i].second);
			//联通 
		}
		int cnt=0;
		for(int i=0;i<n;++i)
			if(per[i]==i) cnt++;//攻占后的连通块数量 
		if(cnt>cnt0+1)
			cout<<"Red Alert: City "<<x<<" is lost!"<<'\n';
		else cout<<"City "<<x<<" is lost."<<'\n';
		if(lostnum==n) cout<<"Game Over."<<'\n';
		cnt0=cnt;
		
	}
	return 0;
}

L2-2 秀恩爱分得快

古人云:秀恩爱,分得快。

互联网上每天都有大量人发布大量照片,我们通过分析这些照片,可以分析人与人之间的亲密度。如果一张照片上出现了 K 个人,这些人两两间的亲密度就被定义为 1/K。任意两个人如果同时出现在若干张照片里,他们之间的亲密度就是所有这些同框照片对应的亲密度之和。下面给定一批照片,请你分析一对给定的情侣,看看他们分别有没有亲密度更高的异性朋友?

输入格式:

输入在第一行给出 2 个正整数:N(不超过1000,为总人数——简单起见,我们把所有人从 0 到 N-1 编号。为了区分性别,我们用编号前的负号表示女性)和 M(不超过1000,为照片总数)。随后 M 行,每行给出一张照片的信息,格式如下:

K P[1] ... P[K]

其中 K(≤ 500)是该照片中出现的人数,P[1] ~ P[K] 就是这些人的编号。最后一行给出一对异性情侣的编号 A 和 B。同行数字以空格分隔。题目保证每个人只有一个性别,并且不会在同一张照片里出现多次。

输出格式:

首先输出 A PA,其中 PA 是与 A 最亲密的异性。如果 PA 不唯一,则按他们编号的绝对值递增输出;然后类似地输出 B PB。但如果 A 和 B 正是彼此亲密度最高的一对,则只输出他们的编号,无论是否还有其他人并列。

输入样例 1:

10 4
4 -1 2 -3 4
4 2 -3 -5 -6
3 2 4 -5
3 -6 0 2
-3 2

输出样例 1:

-3 2
2 -5
2 -6

输入样例 2:

4 4
4 -1 2 -3 0
2 0 -3
2 2 -3
2 -1 2 
-3 2

输出样例 2:

-3 2

代码长度限制                                                                                16 KB

时间限制                                                                                        500 ms

内存限制                                                                                        64 MB

思路:

        读入和输出时要注意 “ - ” 标记是男是女。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
const int N=1010;
int n,m;
double g[N][N];
bool xb[N];
int a[N];
int read()
{
	string s;cin>>s;
	bool man=false;
	if(s[0]!='-') man=true;
	else s=s.substr(1,s.size()-1);
	int x=0;
	for(int i=0;i<s.size();++i)
	{
		x*=10;x+=s[i]-'0';
	}
	xb[x]=man;
	return x;
}
double find(int x)
{
	double res=-1;
	for(int i=0;i<n;++i)
		if(xb[x]!=xb[i])
		{
			res=max(res,g[x][i]);
		}
	return res;
}
void out(int x)
{
	if(xb[x]==false) cout<<"-";
	cout<<x;
}
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	cin>>n>>m;
	for(int i=0;i<m;++i)
	{
		int k;cin>>k;double t=1.0/k;
		for(int j=0;j<k;++j) a[j]=read();
		for(int j=0;j<k-1;++j)
		{
			for(int p=j+1;p<k;++p)
			{
				int x=a[j],y=a[p];
				if(xb[x]==xb[y]) continue;
				g[x][y]+=t;g[y][x]+=t;
			}
		}
	}
	int x,y;
	x=read();y=read();
	double mx=0,my=0;
	mx=find(x);my=find(y);
	if(g[x][y]==mx&&mx==my)
	{
		out(x);cout<<" ";out(y);
	}
	else
	{
		for(int i=0;i<n;++i)
		{
			if(xb[i]!=xb[x]&&g[x][i]==mx)
			{
				out(x);cout<<" ";out(i);cout<<'\n';
			}
		}
		for(int i=0;i<n;++i)
		{
			if(xb[i]!=xb[y]&&g[y][i]==my)
			{
				out(y);cout<<" ";out(i);cout<<'\n';
			}
		}
	}
	return 0;
}

L2-3 插松枝

 

人造松枝加工场的工人需要将各种尺寸的塑料松针插到松枝干上,做成大大小小的松枝。他们的工作流程(并不)是这样的:

  • 每人手边有一只小盒子,初始状态为空。
  • 每人面前有用不完的松枝干和一个推送器,每次推送一片随机型号的松针片。
  • 工人首先捡起一根空的松枝干,从小盒子里摸出最上面的一片松针 —— 如果小盒子是空的,就从推送器上取一片松针。将这片松针插到枝干的最下面。
  • 工人在插后面的松针时,需要保证,每一步插到一根非空松枝干上的松针片,不能比前一步插上的松针片大。如果小盒子中最上面的松针满足要求,就取之插好;否则去推送器上取一片。如果推送器上拿到的仍然不满足要求,就把拿到的这片堆放到小盒子里,继续去推送器上取下一片。注意这里假设小盒子里的松针片是按放入的顺序堆叠起来的,工人每次只能取出最上面(即最后放入)的一片。
  • 当下列三种情况之一发生时,工人会结束手里的松枝制作,开始做下一个:

(1)小盒子已经满了,但推送器上取到的松针仍然不满足要求。此时将手中的松枝放到成品篮里,推送器上取到的松针压回推送器,开始下一根松枝的制作。

(2)小盒子中最上面的松针不满足要求,但推送器上已经没有松针了。此时将手中的松枝放到成品篮里,开始下一根松枝的制作。

(3)手中的松枝干上已经插满了松针,将之放到成品篮里,开始下一根松枝的制作。

现在给定推送器上顺序传过来的 N 片松针的大小,以及小盒子和松枝的容量,请你编写程序自动列出每根成品松枝的信息。

输入格式:

输入在第一行中给出 3 个正整数:N(≤103),为推送器上松针片的数量;M(≤20)为小盒子能存放的松针片的最大数量;K(≤5)为一根松枝干上能插的松针片的最大数量。

随后一行给出 N 个不超过 100 的正整数,为推送器上顺序推出的松针片的大小。

输出格式:

每支松枝成品的信息占一行,顺序给出自底向上每片松针的大小。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

8 3 4
20 25 15 18 20 18 8 5

输出样例:

20 15
20 18 18 8
25 5

代码长度限制                                                16 KB

Java (javac)

时间限制                                                             500 ms

内存限制                                                             64 MB

其他编译器

时间限制                                                            400 ms

内存限制                                                            64 MB

 思路:

        看懂题,总结,模拟。具体看代码注释。

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
stack<int> s;
queue<int> q;
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	int n,m,k;
	cin>>n>>m>>k;
	for(int i=1;i<=n;++i)
	{
		int a;cin>>a;
		q.push(a);
	}
	while(1)
	{
		vector<int> v;//每棵树 
		while(!s.empty())//优先装盒子 
		{
			int num=s.top(); 
			if(v.size()==0) v.push_back(num),s.pop();
			else
			{
				if(num<=v[v.size()-1]&&v.size()<k)
				//满足条件且还能装下 
				{
					v.push_back(num),s.pop();
				}
				else break;
			}
		}
		if(v.size()==k)//插满了 
		{
			for(int i=0;i<k;++i)
			{
				if(i==0) cout<<v[i];
				else cout<<" "<<v[i];
			}
			cout<<'\n';
		}
		else
		{
			while(!q.empty())
			{
				int num=q.front();
				if(v.size()==0) v.push_back(num),q.pop();
				else
				{
					if(v.size()==k) break;
					if(num<=v[v.size()-1])
					{
						v.push_back(num),q.pop();
					}
					else//装盒子里 
					{
						if(s.size()<m)
						{
							s.push(num);q.pop();
						}
						else break;
					}
				}
			}
			if(v.size()==0) break;
			for(int i=0;i<v.size();i++)
			{
				if(i==0) cout<<v[i];
				else cout<<" "<<v[i];
			}
			cout<<'\n';
		}
	}
	return 0;
}

L2-4 哲哲打游戏

哲哲是一位硬核游戏玩家。最近一款名叫《达诺达诺》的新游戏刚刚上市,哲哲自然要快速攻略游戏,守护硬核游戏玩家的一切!

为简化模型,我们不妨假设游戏有 N 个剧情点,通过游戏里不同的操作或选择可以从某个剧情点去往另外一个剧情点。此外,游戏还设置了一些存档,在某个剧情点可以将玩家的游戏进度保存在一个档位上,读取存档后可以回到剧情点,重新进行操作或者选择,到达不同的剧情点。

为了追踪硬核游戏玩家哲哲的攻略进度,你打算写一个程序来完成这个工作。假设你已经知道了游戏的全部剧情点和流程,以及哲哲的游戏操作,请你输出哲哲的游戏进度。

输入格式:

输入第一行是两个正整数 N 和 M (1≤N,M≤105),表示总共有 N 个剧情点,哲哲有 M 个游戏操作。

接下来的 N 行,每行对应一个剧情点的发展设定。第 i 行的第一个数字是 Ki​,表示剧情点 i 通过一些操作或选择能去往下面 Ki​ 个剧情点;接下来有 Ki​ 个数字,第 k 个数字表示做第 k 个操作或选择可以去往的剧情点编号。

最后有 M 行,每行第一个数字是 0、1 或 2,分别表示:

  • 0 表示哲哲做出了某个操作或选择,后面紧接着一个数字 j,表示哲哲在当前剧情点做出了第 j 个选择。我们保证哲哲的选择永远是合法的。
  • 1 表示哲哲进行了一次存档,后面紧接着是一个数字 j,表示存档放在了第 j 个档位上。
  • 2 表示哲哲进行了一次读取存档的操作,后面紧接着是一个数字 j,表示读取了放在第 j 个位置的存档。

约定:所有操作或选择以及剧情点编号都从 1 号开始。存档的档位不超过 100 个,编号也从 1 开始。游戏默认从 1 号剧情点开始。总的选项数(即 ∑Ki​)不超过 106。

输出格式:

对于每个 1(即存档)操作,在一行中输出存档的剧情点编号。

最后一行输出哲哲最后到达的剧情点编号。

输入样例:

10 11
3 2 3 4
1 6
3 4 7 5
1 3
1 9
2 3 5
3 1 8 5
1 9
2 8 10
0
1 1
0 3
0 1
1 2
0 2
0 2
2 2
0 3
0 1
1 1
0 2

输出样例:

1
3
9
10

样例解释:

简单给出样例中经过的剧情点顺序:

1 -> 4 -> 3 -> 7 -> 8 -> 3 -> 5 -> 9 -> 10。

档位 1 开始存的是 1 号剧情点;档位 2 存的是 3 号剧情点;档位 1 后来又存了 9 号剧情点。

代码长度限制                                                        16 KB

Java (javac)

时间限制                                                                800 ms

内存限制                                                                64 MB

Python (python3)

时间限制                                                                1000 ms

内存限制                                                                64 MB

其他编译器

时间限制                                                                400 ms

内存限制                                                                64 MB

思路:

        每次存档更新,需要时输出。

用二维 ch 记录每次的选择。res记录之前的选择。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int res[N];
vector<int> ch[N];
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;++i) ch[i].push_back(0);
	for(int i=1;i<=n;++i)
	{
		int k;cin>>k;
		for(int j=1;j<=k;++j)
		{
			int x;cin>>x;
			ch[i].push_back(x);
		}
	}
	int ans=1;
	for(int i=1;i<=m;++i)
	{
		int x,j;
		cin>>x>>j;
		if(x==0) ans=ch[ans][j];
		else if(x==1)
		{
			res[j]=ans;
			cout<<ans<<'\n';
		}
		else if(x==2) ans=res[j];
	}
	cout<<ans<<'\n';
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值