2017第八届蓝桥杯决赛B组原题答案及总结

题目

36进制

题目描述

在这里插入图片描述

解题思路

简单题,就是进制转换;但是因为好久没做,第一次把进制当成10处理了。然后测试‘AA’,发现结果不对~~~。
代码展示

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5;
/*
MANY
1040254
*/
int main(){
	cout<<('Z'-'A'+10)<<endl;
	//int ans=('Y'-'A'+10)*1+('N'-'A'+10)*100+('A'-'A'+10)*1000+('M'-'A'+10)*10000; 
	int ans=('Y'-'A'+10)*1+('N'-'A'+10)*1*36+('A'-'A'+10)*1*36*36+('M'-'A'+10)*1*36*36*36;
	cout<<ans<<endl;
	return 0;
}
总结

题目中给出的信息要仔细阅读、充分利用;没有那个‘AA’==370,我一大意都看不出来哪里出错。烦~烦

磁砖样式

题目描述

在这里插入图片描述

解题思路

发现环

题目描述

在这里插入图片描述

解题思路

1.DFS暴搜n次

  • 遍历节点1~n;
  • 对于节点x,用DFS(x,x,cnt)进行搜索,表示从x出发,回到x;ans[cnt]表示第cnt步到达的节点;
    代码展示
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
vector<int>G[maxn];
int ans[maxn];
bool vis[maxn];
int n;
bool flag; 
bool DFS(int s,int x,int cnt){
//	cout<<s<<" "<<x<<" "<<cnt<<endl;
	ans[cnt]=x;
	if(flag)return true;	
	int l=G[x].size();
	vis[x]=1;
	for(int i=0;i<l;i++){
		if(flag)return true;
		int f=G[x][i];
		if(f==s){
		sort(ans,ans+cnt+1);
		for(int i=0;i<=cnt;i++){
			if(i!=0)cout<<" ";
				cout<<ans[i];
		}
		cout<<endl;
		flag=true;
	}
		if(!vis[f]){
			DFS(s,f,cnt+1);
		} 
	} 
	return false;
}
int main(){
	cin>>n;
	int a,b;
	for(int i=0;i<n;i++){
		cin>>a>>b;
		G[a].push_back(b);
	}
	for(int i=1;i<=n;i++){
		memset(vis,0,sizeof(vis));
		vis[i]=1;
		if(DFS(i,i,0))break; 
	}	
	return 0;
}

但是这样计算,无法通过所有的测试点;样例与自测都能通过;暂时还不知道为什么 ~
2.并查集+DFS

  • 先用并查集求出这条环上的两点;
  • 再用DFS(s,f),搜索s能到达的点,直到s==f;
  • 但是有个问题需要解释:
    –为什么它能一次就访问到环上的所有点;
    在这里插入图片描述
    代码展示
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5;
/*
1.找出环上的两点(并查集)
2.DFS深搜 
=========
总结
1.注意maxn范围,一定+5 
2.void的DFS可以没有返回值,但bool类型的一定要有
3.什么时候需要回溯?什么时候不需要回溯 
*/
vector<int>G[maxn];
int ans[maxn];
int Fa[maxn];
int vis[maxn];
int cnt;
int Find(int x){
	return x==Fa[x] ? x:Fa[x]=Find(Fa[x]);
}
void DFS(int s,int t,int cnt){
	vis[s]=1;
	ans[cnt]=s;
	if(s==t){
		sort(ans,ans+cnt+1);
		//cout<<cnt<<endl;
		for(int i=0;i<=cnt;i++){
			if(i!=0)cout<<" ";
			cout<<ans[i];
		}
		return;
	}
	for(int i=0;i<G[s].size();i++){
		int f=G[s][i];
		if(!vis[f])
			DFS(f,t,cnt+1);
	}
}
int main(){
	int n;
	scanf("%d",&n);
	int a,b;
	int s,t;
	for(int i=1;i<=n;i++)Fa[i]=i;
	for(int i=0;i<n;i++){
		scanf("%d%d",&a,&b);
		
		int fa=Find(a),fb=Find(b);
		if(fa!=fb){
			Fa[fa]=fb;
		}
		else {
			s=a,t=b;
		}	
		G[a].push_back(b);
		G[b].push_back(a);
	}
	//cout<<s<<" "<<t<<endl;
	DFS(s,t,0);
	return 0;
}

对局匹配

题目描述

在这里插入图片描述

解题思路

1.数据分组+DP

  • 把数据分成每组之间相差为k的k组数据,即{0,k,2k,3k~~~,n*k},;
  • 那么不难发现各组数据之前是不会相互匹配的;
  • 而对于每一组数据,我们可以当成打家劫舍问题求解,即不能选择相邻的两个数(差为k);
  • 所以,最大的在线人数就是各组选择人数之和;
  • 复杂度为O(maxn),是个常数;
    代码展示
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
/*
1.
10 0
1 4 2 8 5 7 1 4 2 8
10 1
2 1 1 1 1 4 4 3 4 4
====
思路:
1.把数据按照相差k来分组 
2.对与每组数据,当作 打家劫舍问题 处理 
*/
int num[maxn];
int val[maxn];
int main(){
	int n,k;
	cin>>n>>k;
	int x;
	int ans=0;
	for(int i=0;i<n;i++){
		cin>>x;
		if(!num[x])
			ans++;
		num[x]++;
	}
	if(k!=0){
		ans=0;
		for(int i=0;i<k;i++){
			int t=0;
			for(int j=i;j<=maxn;j+=k){
				val[t++]=num[j];
			}//生成一组差值为k的数据
			int fir=val[0],sec=max(val[0],val[1]);
			for(int j=2;j<t;j++){
				int temp=max(sec,fir+val[j]);
				fir=sec;
				sec=temp;
			} 
			ans+=sec;
		}
	}
	cout<<ans<<endl;
	return 0;
}

观光铁路

题目描述

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210420103623300.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2FscGhhX3hpYQ==,size_16,color_FFFFFF,t_70

解题思路

    发

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高冷小伙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值