2023蓝桥杯省赛c++b组

蓝桥杯真题(更新至2023年) - 编程题库 - C语言网 (dotcpp.com)

AB不想手打数据,等有真题了再说吧。

C冶炼金属

思路:这题我写了几个数,发现就是取一堆数据的最小值的最大值,和最大值的最小值(人话:公共部分)。看样例的解释,凑出的通式。

#include
#include
#include
#include
#include
#include
#include
#include

#define maxn 500010
//#define ll long long
#define int long long

int n;
int a, b;
int minn = 0, maxx = 0x3f3f3f3f3f;
int x, y;
using namespace std;

void solve()
{

	cin >> n;

	for (int i = 1; i <= n; i++) {
		cin >> a >> b;
		x = a * 1.0 / (b + 1)+1;
		y = a * 1.0 / b;
		minn = max(x, minn);
		maxx = min(y, maxx);
	}
	cout <> t;
	//while(t--)
	solve();
	return 0;
}

 二分:

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using  pii = pair;

#define maxn 10010
//#define ll long long
#define int long long
const int inf = 0x3f3f3f3f3f;

//map, int>flag;
int d[maxn];
int a[maxn], b[maxn];
int n;

 int two1(int x)
 {
     for (int i = 1; i <= n; i++)
         if (a[i] / x < b[i])
             return 0;
     return 1;
 }
 int two2(int x)
 {
     for (int i = 1; i <= n; i++)
         if (a[i] / x > b[i])
             return 0;
     return 1;
 }

void solve()
{
    cin >> n;
    int maxx = 0, minn = inf;
    int l = 1, r = n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i] >> b[i];
        r = max(a[i], r);
    }
    int mm = r;
    while (l <= r)
    {
        int mid = (l + r) / 2;
        if (two1(mid))
            l = mid+1;
        else
            r = mid-1;
    }
    maxx = l;
    r = mm;
    l = 1;
    while (l < r)
    {
        int mid = (l + r) / 2;
        if (two2(mid))
           r = mid;
        else
           l = mid+1;
    }
    minn = l;
    cout <> t;
    while(t--)
    solve();
    return 0;
}

 

D飞机降落

思路:看注释即可

#include
#include
#include
#include
#include
#include
#include
#include

#define maxn 20
#define ll long long
#define int long long

int n, t[maxn], d[maxn], l[maxn],flag,f[maxn];
//n:飞机数;
//t[]:到达时间
//d[]:盘旋时间
//l[]:落地所需时间
//flag:是否能全都塞下
//f[]:是否来过这个
using namespace std;
void dfs(int x,int tim)
{
	if (flag )
		return;
	if (x == n)
	{
		flag = 1;
		return;
	}
	for (int i = 1; i <= n; i++)
	{
		//暴力深搜,只要当前时间小于当前飞机最晚降落时间就进入判断
		if (f[i] == 0 && tim <= t[i] + d[i])
		{
		    f[i] = 1;//来过
			//dfs(已经安排下的飞机的个数,此飞机到地面的时间)
			dfs(x + 1, max(t[i], tim) + l[i]);
			//t[i]是到达时间,tim则是当前时间可能会让飞机盘旋一会儿
			if (flag)
				return;
			f[i] = 0;//防止影响其他路径的标记
		}
	}
}
void solve()
{
	memset(t, 0, sizeof(t));
	memset(d, 0, sizeof(d));
	memset(l, 0, sizeof(l));
	memset(f, 0, sizeof(f));
	flag = 0;
	cin >> n;
	for(int i=1;i<=n;i++)
		cin >> t[i] >> d[i] >> l[i];
	dfs(0, 0);
	if (flag)
		cout << "YES" << endl;
	else
		cout << "NO" << endl;
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
	return 0;
}

E: 接龙数列

思路:在注释里

#include
#include
#include
#include
#include
#include
#include
#include

#define maxn 20
#define ll long long
#define int long long

int dp[10];
//也就10种可能结尾0~9
//dp[i]为以i为结尾的最长长度。
using namespace std;

void solve()
{
	int n;
	cin >> n;
	string x;
	for (int i = 1; i <= n; i++)
	{
		cin >> x;
		int a = x[0] - '0', b = x.back() - '0';
		//dp[b]是以b结尾当前最长的接龙序列,
		//当前要最长,就要把上一个以a为结尾的序列加上本个的长度,和以b为结尾的序列比较。
	
		dp[b] = max(dp[b], dp[a] + 1);
	}
	int maxx=0;
//看看哪个结尾的序列最长
	for (int i = 0; i < 10; i++)
	{
		maxx = max(dp[i], maxx);
	}
	cout << n-maxx << endl;
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	/*int t;
	cin >> t;
	while(t--)*/
	solve();
	return 0;
}

F 岛屿个数

思路:一开始我想错了,把子岛也求了。这题两遍搜索就能做,我习惯深搜。第一遍把岛屿外面的0全改成2(8方搜索),然后把里面的0改成1,第二for循环搜索遍历岛屿(四方搜索),看看有几个。

为什么第一遍8方,第二遍四方呢。首先我们要知道只有有公共边才算同一个岛屿,举个例子:

0 2 1 0                           0 1 1 0

0 1 3 0                           0 1 0 0

   图一                                  图二

假设一下,岛屿外是海,岛屿内是河。图中是有两个岛的,图1的3点是海,2点也是,2点8方可以搜到3,他们也算是联通的;同理,图二只有一个岛。


#include
#include
#include
#include
#include
#include
#include
#include

#define maxn 20
#define ll long long
//#define int long long


int n, m;
int k = 0;
char g[55][55];
int d4[4][2] = { {0,1},{0,-1},{-1,0},{1,0} };
int d8[8][2] = { {0,1},{0,-1},{-1,0},{1,0},{-1,1},{-1,-1},{1,-1},{1,1} };
//可以深搜一条路径,每一步+1(即求长度),但是注意要从2开始,最后看有几个2
//也可以一条路径都是一个数,看看图中最大数是几

using namespace std;

void  dfs1(int x, int y)
{
	g[x][y] = '2';
	for (int p = 0; p < 8; p++)
	{
		int dx = x + d8[p][0], dy = y + d8[p][1];
		if (dx >= 0 && dx <= m+1 && dy >= 0 && dy <= n+1 && g[dx][dy] == '0')//
			dfs1(dx, dy);
	}
	return;
}
void  dfs2(int x, int y)
{
	g[x][y] = '0';//这里只要不是1就行,随便改
	for (int p = 0; p < 4; p++)
	{
		int dx = x + d4[p][0], dy = y + d4[p][1];
		if (dx >= 1 && dx <= m && dy >= 1 && dy <= n && g[dx][dy] == '1')
			dfs2(dx, dy);
	}
	return;
}
void solve()
{
	k = 0;
	memset(g,'0', sizeof(g));
	cin >> m>>n;
	for(int i=1;i<=m;i++)
		for (int j = 1; j <= n; j++)
			cin >> g[i][j];
	dfs1(0,0);
	for (int i = 0; i <= m+1; i++)
		for (int j = 0; j <= n+1; j++)//这里是为了保证所有岛屿外面有水,并且通过dfs让水2灌满所有没岛的地方
			if (g[i][j] == '0')
				g[i][j] = '1';
	//cout << endl;
	//for (int i = 0; i <= m+1; i++)
	//{
	//	for (int j = 0; j <= n+1; j++)
	//		cout << g[i][j];
	//	cout << endl;
	//}
	for(int i=0;i<=m+1;i++)
		for (int j = 0; j <= n+1; j++)
		{
			if (g[i][j] == '1')
			{
				dfs2(i,j);
				k++;
			}
		}
		//cout << endl;
	cout << k << endl;
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
	return 0;
}

 G子串个数

思路:找到所有头l和尾r出现的位置,然后存起来。利用r[j] >= l[i] + k - 1这一关系,找出每一个头的总数,加和即可。

#include
#include
#include
#include
#include
#include
#include
#include

#define maxn 500010
//#define ll long long
#define int long long



using namespace std;

void solve()
{
	int k;
	cin >> k;
	string s;
	char a, b;
	cin >> s>>a>>b;
	//cout << s <= 1; j--)
	//		if (r[j] < l[i]+k-1)//第j个右点小于基点,也就是从这开始不能形成字符串
	//		{
	//			ans += rr - j;//减去即可
	//			break;
	//		}
	//}
	//上述暴力仅能95分,我们再优化一下。我们可以注意到前面很多点其实是无效重复跑的。
	//比如说ababb,k=2.第一个b肯定是无效的,但是我们还在跑;第二个b生效一次之后,
	//只有后面的b有效,所以我们可以找个数存一下,以后查询直接跳过去。
	int temp = 1;
	for (int i = 1; i <= ll; i++)
	{
		for (int j = temp; j <= rr; j++)
		{
			//倒着跑是找第一个小于的,正着跑是找第一个大于的再-1。
			if (r[j] >= l[i] + k - 1)//第j个右点小于基点,也就是从这开始不能形成字符串
			{
				temp = j;
				ans += rr - j+1;//减去即可
				//这里的+1大家可能没明白,就比如说第j个开始就符合条件,那我们就用"总数-(j-1)"对吧,也就是这里的-j+1
				break;
			}
		}
	}
	cout << ans;
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	//int t;
	//cin >> t;
	//while(t--)
	solve();
	return 0;
}

你可能感兴趣的:(蓝桥杯,蓝桥杯)