首页 > 其他分享 >纯小白蓝桥杯备赛笔记--DAY9(搜索)

纯小白蓝桥杯备赛笔记--DAY9(搜索)

时间:2024-04-03 16:30:21浏览次数:22  
标签:nx return 杯备赛 DAY9 int cin dfs 蓝桥 dep

文章目录

三道例题学会DFS剪枝

什么是剪枝

  • 其实就是将搜索过程当中一些不必要的部分直接别除掉,因为搜索过程构成了一棵树,别除不必要的部分,就像是在树上将树枝剪掉,故名剪枝。
  • 剪枝是回溯法的一种重要优化手段,方法往往先写一个暴力搜索,然后找到某些特殊的数学关系,或者逻辑关系,通过它们的约束让搜索树尽可能浅而小,从而达到降低时间复杂度的目的。
  • 一般来说,剪枝的复杂度难以计算。

进入例题提示:如果理解不了的同学建议先看第二部分DFS回溯。

数字王国之军训排队–2942

在这里插入图片描述

  • 向下递归的搜索过程。这里的剪枝策略是当中间出现不合法的情况就跳过。
  • 如果不剪枝就是留到递归出口那去检查,这样做效率是比较慢的。
  • 先写一段不剪枝的方法对比一下。
#include<bits/stdc++.h>
using namespace std;
const int N=15;
int a[N],n;
vector<int>v[N];//存放队伍,例:v1就是队伍1中所有成员的 编号,v2是队伍2中所有成员的编号 
//搜索,dfs返回在cnt个队伍的情况下能否成功分组 
bool dfs(int cnt,int dep)//这里的cnt是队伍的个数 
{
	if(dep==n+1)//递归出口,每个人都成功分组了 
	{return true; 
		//检查当前方案的合法性
		 for(int i=1;i<=cnt;i++)//对每一个队伍进行检查 
		 {
		 	for(int j=0;j<v[i].size();j++)
			 {
			 	for(int k=j+1;k<v[i].size();k++)//这两个循环是枚举所有的二元组 
			 	{
//			 		if(j==k)continue;//相等,退出,注释掉的原因是k从j+1开始,不会相等 
					 if(v[i][k]%v[i][j]==0)return false; 
				 }
			  } 
		  } 
		return true;
	 } 
	 //枚举每一个所属的队伍
	 for(int i=1;i<=cnt;i++)
	 {
	 	v[i].push_back(a[dep]);
	 	if(dfs(cnt,dep+1))return true;//合法
		 //恢复现场
		 v[i].pop_back(); 
	  } 
	  return false;//不存在 
 } 

int main()
{
 	cin>>n;
 	for(int i=1;i<=n;i++)cin>>a[i];
 	sort(a+1,a+n+1);//排序是不影响结果的 
 	//枚举这n个队伍,极端情况就是每个人单独成一队 
	for(int i=1;i<=n;i++)
	{
		if(dfs(i,1));//在i个队伍的情况下,检查深度为1层,如果当前可以成功分组,那么i就是最小的分组个数 
		{
			cout<<i<<'\n';
			break;//找到结果就可以跳出循环了 
		}
	}
	return 0;
 } 
  • 接下来看剪枝的写法:
#include<bits/stdc++.h>
using namespace std;
const int N=15;
int n;
int a[N];
vector<int> vec[N];//二维vector这样定义,别用vector<vector<int>> vec,因为前者外部vector已声明大小,可以直接调用迭代器,后者不行 
bool dfs(int dep,int i)//dep为第几个学生,i为分几队 
{//dfs用于判断是否可以分为i队 
    if(dep==n+1) return true;//如果递归到了最底层,说明可以分成i队 

    for(int j=0;j<i;j++)//将当前dep学生分到j队 
    {    bool flag=false;
        for(const auto &b:vec[j]) //遍历二维vector,遍历vector用auto枚举比较方便, 
        {
        //这种题型与组合枚举不一样,不要用两条件来思考 
            if(a[dep]%b==0) //如果当前将要入队的数字学生与队里面的数字可以整除,即有倍数关系 
            {                 //因为用sort排过序,所以a[dep]一定比b大 
                flag=true;break;
            }
             
            
        }
        if(flag) continue;
        vec[j].push_back(a[dep]);
        if(dfs(dep+1,i)) return true;//布尔dfs的递归这样写,若为false仍需执行后面的恢复现场语句 
        //恢复现场 
        vec[j].pop_back();
    }
    return false; //中间执行完后没有return true,则return false 
}
int main()
{
 	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+n+1);
     for(int i=1;i<=n;i++)//将1到n队都试试 
     {
         if(dfs(1,i)) //第一个可行的队即为最少的队 
         {
             cout<<i;
             break;
         }
     }
    return 0;
}

特殊的三角形–3008

在这里插入图片描述

  • 解析:
    在这里插入图片描述
  • 具体实现:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+9;
int n;
int st;
int cnt[N];//乘积为i的三元组有多少个
int prefix[N];//定义前缀和数组 
//dfs
void dfs(int dep,int st,int mwl,int sum)//sum是前面两条边的和 
{
	//剪枝
	if(mwl>1e6) return ;
	if(dep==4)
	{
		cnt[mwl]++;
		return;
	}
	int up=pow(1e6/mwl,1.0/(3-dep+1))+3;//得到上限
	for(int i=st+1;i<(dep==3?sum:up);i++)
	{
		dfs(dep+1,i,mwl*i,sum+i);
	 } 
 } 
int main()
{
 	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  	dfs(1,0,1,0);
	for(int i=1;i<=1e6;i++)
	{
	    prefix[i]=prefix[i-1]+cnt[i];
	 } 
	 int q;cin>>q;
	 while(q--)
	 {
	 	int l,r;cin>>l>>r;//输入区间
		 cout<<prefix[r]-prefix[l-1]<<"\n"; 
	 }
    
    return 0;
}

特殊的多边形–3075

和上一题比较像,只需要修改部分内容如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+9;
int n;
int st;
int cnt[N];//乘积为i的三元组有多少个
int prefix[N];//定义前缀和数组 
//dfs
void dfs(int dep,int st,int mwl,int sum)//sum是前面两条边的和 
{
	//剪枝1
	if(mwl>1e5) return ;
	if(dep==n+1)
	{
		cnt[mwl]++;
		return;
	}
	//剪枝2 
	int up=pow(1e6/mwl,1.0/(n-dep+1))+3;//得到上限
	//剪枝3,构造递增 
	for(int i=st+1;i<(dep==n?min(sum,up):up);i++)//虽然是n边形,但是最后一位的长度依然不能超过sum 
	{
		dfs(dep+1,i,mwl*i,sum+i);
	 } 
 } 
int main()
{
 	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); 
	 int q;cin>>q>>n;
	 dfs(1,0,1,0);
	for(int i=1;i<=1e5;i++)
	{
	    prefix[i]=prefix[i-1]+cnt[i];
	 }
	 while(q--)
	 {
	 	int l,r;cin>>l>>r;//输入区间
		 cout<<prefix[r]-prefix[l-1]<<"\n"; 
	 }
    
    return 0;
}

DFS基础回溯

简介

  • 回溯法一般使用DFS(深度优先搜索)实现,DFS是一种遍历或搜索图、树或图像等数据结构的算法,当然这个图、树未必要存储下来(隐式处理就是回溯法),常见的是通过某种关系构造出的搜索树,搜索树一般是排列型搜索树(总节点个数一般为n!级别)和子集型搜索树(总节点个数一般为2^n级别)。
  • 排列型就是每次枚举选哪个,子集型就是对于每一个元素选或不选(结果与顺序无关)。
  • DFS从起始节点开始,沿着一条路径尽可能深入地搜索(一条路走到黑),直到无法继续为止,然后回潮到前一个节点,继续探索其他路径,直到遍历完整个图或树。
  • DFS使用栈或递归来管理节点的遍历顺序,一般使用递归。很多时候DFS和回溯法不必过度区分。
  • 排列树图解:1~3的全排列
    在这里插入图片描述
  • 子集树在这里插入图片描述

回溯法模版

//求1~n的全排列
int a[N];
bool vis[N];//表示是否被使用过
void dfs(int dep)//dep表示深度 
{
	//1.首先考虑递归出口的问题 
	if(dep==n+1)
	{
		for(int i=1;i<=n;i++) cout<<a[i]<<' ';
		cout<<"\n";
		return;
	}
	//2.向下搜索
	for(int i=1;i<=n;i++)
	{
		//2.1先排除不合法的路径
		if(vis[i]) continue;//表示i已经被使用过,全排列中1 2 1这种形式不能出现
		//2.2修改状态
		vis[i]=true;
		a[dep]=1;//i可以被使用,并且此时的递归层达到i
		//2.3下一层
		dfs(dep+1);
		//2.4恢复现场
		vis[i]=false;
		//a[dep]=0可以省略 
	 } 
 } 

例题

N皇后–1508

在这里插入图片描述

  • 分析
    在这里插入图片描述
#include<iostream>
using namespace std;

const int N = 12;
int vis[N][N], n, ans;

void dfs(int dep)
{
    // 在这个搜索中dep表示行,i表示列
    // 1 搜索出口
    if(dep == n + 1)
    {
        ans++;
        return;
    }
    // 2 继续搜索
    for(int i = 1; i <= n; ++i)
    {
        // 2.1 排除非法情况
        if(vis[dep][i])
            continue;
        // 2.2 改变状态
        for(int _i = 1; _i <= n; ++_i)
            vis[_i][i]++;
        for(int _i = dep, _j = i; _i >= 1 && _j >= 1; --_i, --_j)
            vis[_i][_j]++;
        for(int _i = dep, _j = i; _i <= n && _j >= 1; ++_i, --_j)
            vis[_i][_j]++;
        for(int _i = dep, _j = i; _i >= 1 && _j <= n; --_i, ++_j)
            vis[_i][_j]++;
        for(int _i = dep, _j = i; _i <= n && _j <= n; ++_i, ++_j)
            vis[_i][_j]++;
        // 2.3 下一层
        dfs(dep + 1);
        // 2.4 还原现场
        for(int _i = 1; _i <= n; ++_i)
            vis[_i][i]--;
        for(int _i = dep, _j = i; _i >= 1 && _j >= 1; --_i, --_j)
            vis[_i][_j]--;
        for(int _i = dep, _j = i; _i <= n &&  _j >= 1; ++_i, --_j)
            vis[_i][_j]--;
        for(int _i = dep, _j = i; _i >= 1 && _j <= n; --_i, ++_j)
            vis[_i][_j]--;
        for(int _i = dep, _j = i; _i <= n && _j <= n; ++_i, ++_j)
            vis[_i][_j]--;
    }
}

int main()
{
    cin >> n;
    dfs(1);
    cout << ans << "\n";
    return 0;
}

小朋友崇拜圈–182

在这里插入图片描述

  • 解析
    在这里插入图片描述
  • 代码:
#include<bits/stdc++.h>
using namespace std;
const int N= 1e5 + 10;
int a[N],dfn[N]; 
int n,idx,mindfn;
int dfs(int b)
{
    dfn[b]=++idx;//时间戳 
    if(dfn[a[b]]==0) return dfs(a[b]);//要有return ,若时间戳为空,继续递归 
    else//有时间戳的情况 
    {
        if(dfn[a[b]]>=mindfn) return dfn[b]-dfn[a[b]]+1;//下一个崇拜对象大于等于最小时间戳,说明闭环 
        return 0;//下一个崇拜对象小于最小时间戳,说明不闭环 
    }
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int maxs=0;
    for(int i=1;i<=n;i++) //从dfn为空的开始递归 
    {
        if(dfn[i]==0)
        {
            mindfn=idx+1;//更新最小时间戳 
        maxs=max(dfs(i),maxs);//取所有环中的最大值 
        }
    }
    cout<<maxs<<endl;    
    return 0;
}

  • 第二种形式–dfs中有一点点不同
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e5+9;
int n,a[N],dfn[N],mindfn;
int idx;//这是一个正在变化的数字,表示此时的时间 
int ans;
int dfs(int x)
{
	dfn[x]=++idx;
	//递归出口 
	if(dfn[a[x]])
	{
		if(dfn[a[x]]>=mindfn)
		return dfn[x]-dfn[a[x]]+1;
	 	return 0;	
	}
	return dfs(a[x]); 
}
int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		if(!dfn[i])
		{
			mindfn=idx+1;//更新
			ans=max(ans,dfs(i)); 
		}
	}
	cout<<ans<<endl;
}
全球变暖–178

在这里插入图片描述

  • 分析:在这里插入图片描述
  • 代码:
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e3+5;
int n;
char mp[N][N];
int scc,col[N][N];
int dx[]={0,0,1,-1};//表示四个方向的偏移量
int dy[]={1,-1,0,0}; 
bool vis[N*N];//表示某种颜色是否剩下来 
void dfs(int x,int y)
{
	col[x][y]=scc; 
	for(int i=0;i<4;i++)//i往四个方向走 
	{
		int nx=x+dx[i];//下一个x的位置
		int ny=y+dy[i];
		if(col[nx][ny]||mp[nx][ny]=='.')continue;//海洋!不要过去 
//		第一个条件是说:如果已经有颜色了就不要再走,否则会造成两个点反复横跳 
		dfs(nx,ny);//因为题干中保证了边缘是海洋,所以不用判断了 
	}
 } 
int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>mp[i]+1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(col[i][j]||mp[i][j]=='.')continue;//如果是海洋,跳过
			scc++;//当前的颜色编号加1 
			dfs(i,j);
		}
	}
	//进行淹没
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(mp[i][j]=='.')continue;//特判,防止超出地图 
			bool tag=true;//默认颜色会剩下来(四个方向都有陆地)
			for(int k=0;k<4;k++)//往四个方向走 
			{
				int x=i+dx[k];
				int y=j+dy[k];
				if(mp[x][y]=='.')tag=false;
			 } 
			 if(tag)
			 {
			 	if(!vis[col[i][j]])ans++;//如果这个颜色没有出现过,答案++ 
			 	vis[col[i][j]]=true; 
			 }
		 } 
	 } 
	 cout<<scc-ans<<endl;
	 return 0;
}

记忆化搜索

简介

  • 就是将搜索过程中会重复计算且结果相同的部分保存下来,作为一个状态,下次访问到这个状态时直接将这个子搜索的结果返回,而不需要再重新算一遍。
  • 通常会使用数组map来进行记忆化,下标一般和dfs的参数表对应。
  • 注意使用记忆化需要保证重复计算的结果是相同的,否则可能产生数据失真。

斐波那契数列

在这里插入图片描述
如果直接采用递归来做,时间复杂度将接近O(2^),但是我们会发现有大部分的重复计算,比如F[n- 2]在求F[n]的时候算过,在求F[n-1]的时候又被算了一次,而F[1]计算次数更多了,但它们在重复的时候的结果是相同的,所以可以采用记忆化(也叫带备忘录的搜索)。

  • 如果采用原来的方法:
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll p=1e9+7;
const int inf=1e9,N=1e3+3;
ll f(int n)
{
	if(n<=2)return 1;
	else
	return (f(n-1)+f(n-2))%p;
}

int main()
{
	int n;cin>>n;
	cout<<f(n)<<endl;
	return 0;
}

可以发现,当输入值为50的时候计算就非常慢了。

  • 增加备忘录:
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll p=1e9+7;
const int inf=1e9,N=1e5+3;
ll dp[N];
ll f(int n)
{
	if(n<=2)return 1;
	if(dp[n]!=-1)return dp[n];//被算过才能直接返回 
	else
	return dp[n]=(f(n-1)+f(n-2))%p;
}

int main()
{
	memset(dp,-1,sizeof dp);//初始化dp数组 ,dp为-1代表还没有被算过 
	int n;cin>>n;
	cout<<f(n)<<endl;
	return 0;
}

这下输入5000也可以直接算出来啦。
在这里插入图片描述

  • 之前的文章中提到过memset函数,这里再次说一下用法:

C++中的memset函数用于将一段内存区域的内容设置为指定的值。它的原型如下:
cpp
复制代码运行
void* memset(void* ptr, int value, size_t num);
参数说明:
ptr:指向要填充的内存区域的指针。
value:要设置的值,以int形式给出,但实际上是按unsigned char类型处理的。
num:要设置的字节数。
返回值:返回指向填充后的内存区域的指针。

混境之地5-3820

在这里插入图片描述

  • 未加记忆化搜索:
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e3+3;
int n,m,k;//起点,终点和高度
int sx,sy,fx,fy; 
int h[N][N];//高度数组 
int dx[]={0,0,1,-1};//表示四个方向的偏移量
int dy[]={1,-1,0,0}; 
bool inmap(int x,int y)//判断是否在地图之中 
{
	return 1<=x&&x<=n&&1<=y&&y<=m; 
}
//返回值表示能否到达终点(fx,fy)
bool dfs(int x,int y,int t)//t表示当前使用的喷气背包的次数 
{
	if(x==fx&&y==fy)return true;//到达终点
	 for(int i=0;i<4;i++)
	 {
	 	int nx=x+dx[i];//下一个方向
	    int ny=y+dy[i];
		if(!inmap(nx,ny))continue;//不在地图内,返回
		if(!t)//没用过背包 
		{
			//不用 
			if(h[x][y]>h[nx][ny]&&dfs(nx,ny,0))return true; 
			//用
			if(h[x][y]+k>h[nx][ny]&&dfs(nx,ny,1))return true; 
		 }
		 else
		 {
		  	//只能不用 
			if(h[x][y]>h[nx][ny]&&dfs(nx,ny,1))return true;
		  } 
	 }
	 return false; 
 } 
int main()
{
	//控制输入 
	cin>>n>>m>>k;
	cin>>sx>>sy>>fx>>fy;
 	for(int i=1;i<=n;i++)
 	{
 		for(int j=1;j<=m;j++)
 		{
 			cin>>h[i][j];
		 }
	 }
	 cout<<(dfs(sx,sy,0)?"Yes":"No")<<endl;
	return 0;
}
  • 加上记忆化搜索:
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e3+3;
int n,m,k;//起点,终点和高度
int sx,sy,fx,fy; 
int h[N][N];//高度数组 
int dx[]={0,0,1,-1};//表示四个方向的偏移量
int dy[]={1,-1,0,0}; 
int dp[N][N][2];//这里不能用bool 
bool inmap(int x,int y)//判断是否在地图之中 
{
	return 1<=x&&x<=n&&1<=y&&y<=m; 
}
//返回值表示能否到达终点(fx,fy)
bool dfs(int x,int y,int t)//t表示当前使用的喷气背包的次数 
{
	if(x==fx&&y==fy)return true;//到达终点
	if(dp[x][y][t]!=-1)return dp[x][y][t];
	 for(int i=0;i<4;i++)
	 {
	 	int nx=x+dx[i];//下一个方向
	    int ny=y+dy[i];
		if(!inmap(nx,ny))continue;//不在地图内,返回
		if(!t)//没用过背包 
		{
			//不用 
			if(h[x][y]>h[nx][ny]&&dfs(nx,ny,0))return dp[x][y][t]=true; 
			//用
			if(h[x][y]+k>h[nx][ny]&&dfs(nx,ny,1))return dp[x][y][t]=true; 
		 }
		 else
		 {
		  	//只能不用 
			if(h[x][y]>h[nx][ny]&&dfs(nx,ny,1))return dp[x][y][t]=true;
		  } 
	 }
	 return dp[x][y][t]=false; 
 } 
int main()
{
	memset(dp,-1,sizeof dp);
	//控制输入 
	cin>>n>>m>>k;
	cin>>sx>>sy>>fx>>fy;
 	for(int i=1;i<=n;i++)
 	{
 		for(int j=1;j<=m;j++)
 		{
 			cin>>h[i][j];
		 }
	 }
	 cout<<(dfs(sx,sy,0)?"Yes":"No")<<endl;
	return 0;
}

地宫取宝-216

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll p=1e9+7;
const int N=55;
int n,m,k;//起点,终点和高度
int c[N][N];//高度数组 
int dx[]={0,1};//表示四个方向的偏移量
int dy[]={1,0}; 
int dp[N][N][15][15];//这里不能用bool 
bool inmap(int x,int y)//判断是否在地图之中 
{
    return 1<=x&&x<=n&&1<=y&&y<=m; 
}
//表示从(1,1)到(x,y),有cnt件宝贝,且最大值为mx的方案数 
ll dfs(int x,int y,int mx,int cnt)//t表示当前使用的喷气背包的次数 
{
    if(x==n&&y==m)return (ll)(cnt==k);//到达终点
    if(dp[x][y][mx][cnt]!=-1)return dp[x][y][mx][cnt];
    ll res=0;//方案数 
    for(int i=0;i<2;i++)
    {
        int nx=x+dx[i];//下一个方向
        int ny=y+dy[i];
        if(!inmap(nx,ny))continue;//不在地图内,返回
        //拿这个宝贝
        if(c[nx][ny]>mx&&cnt<k) res=(res+dfs(nx,ny,c[nx][ny],cnt+1))%p;
        //不拿这个宝贝
        res=(res+dfs(nx,ny,mx,cnt))%p; 
    }
    return dp[x][y][mx][cnt]=res; 
} 
int main()
{
    memset(dp,-1,sizeof dp);
    //控制输入 
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>c[i][j];
            c[i][j]++;
        }
    }
    cout<<(dfs(1,1,0,0)+dfs(1,1,c[1][1],1))%p;//不拿和拿了 
    return 0;
}

标签:nx,return,杯备赛,DAY9,int,cin,dfs,蓝桥,dep
From: https://blog.csdn.net/Yhvaely/article/details/137168102

相关文章

  • 备战蓝桥杯之填空题技巧(持续更新)
    前言本刷题系列是我为了蓝桥杯前几天可以再系统性思考一下真题所做,所以部分内容会很简洁。如果能够帮助到你,我也会很开心!!!题目110.工作时长-蓝桥云课(lanqiao.cn)截图:excel解题:首先先点击数据排序,排好序后每两行进行计算,用后面的一行减去前面的一行,合并前两个单元格往......
  • 【洛谷 P8695】[蓝桥杯 2019 国 AC] 轨道炮 题解(映射+模拟+暴力枚举+桶排序)
    [蓝桥杯2019国AC]轨道炮题目描述小明在玩一款战争游戏。地图上一共有NNN个敌方单位,可以看作2D平面上的点。其中第i......
  • 【洛谷 P8672】[蓝桥杯 2018 国 C] 交换次数 题解(字符串+映射+全排列)
    [蓝桥杯2018国C]交换次数题目描述IT产业人才需求节节攀升。业内巨头百度、阿里巴巴、腾讯(简称BAT)在某海滩进行招聘活动。招聘部门一字排开。由于是自由抢占席位,三大公司的席位随机交错在一起,形如:ABABTATT,这使得应聘者十分别扭。于是,管理部门要求招聘方进行必要的......
  • 【洛谷 P8700】[蓝桥杯 2019 国 B] 解谜游戏 题解(字符串+映射+周期性)
    [蓝桥杯2019国B]解谜游戏题目背景题目描述小明正在玩一款解谜游戏。谜题由242424根塑料棒组成,其中黄色塑料棒4......
  • P8776 [蓝桥杯 2022 省 A] 最长不下降子序列
    1.首先想到的做法设up_len[i]为以a[i]为结尾的最长不下降子序列的长度,down_len[i]表示以a[i]为开始的最长不下降子序列的长度。在求pre的过程中记录下额外信息:down_pre[i]表示在求down_len[i]的过程中,i是由哪个点转移过来的;得到dp的转移方程:if(down_pre[i])ans......
  • 蓝桥杯单片机组第十四届省赛
     1.题目 本次题目模块较多,难度较大  2.底层代码2.1三个常用模块2.1.1按键本次省赛采用了NE555模块,要用P34引脚,在按键底层中,要把P34相关的代码注释掉,并且要将P34引脚用跳线帽(可以用超声波模块的跳线帽)与SIGNAL相连Key.c#include<Key.h>unsignedchar......
  • 蓝桥杯单片机第十三届省赛
    一、题目这次的省赛我感觉还是比较基础的,掌握几个模块就可以完全写出题目是在在网上找的二、代码 main.c#include<STC15F2K60S2.H>#include<ds1302.h>#include<onewire.h>#include<intrins.h>#include<Init.h>#include<Key.h>#include<Seg.h>#include......
  • 蓝桥杯算法集训 - Week 5:树状数组、各类DP算法
    蓝桥杯算法集训-Week5本系列随笔用于整理AcWing题单——《蓝桥杯集训·每日一题2024》的系列题型及其对应的算法模板。一、树状数组树状数组是一种数据结构,可以快速地完成以下两个操作:将第i个数加上c快速求前缀和,即任意区间[i,j]的和Ⅰ、代码模板//树状数组长度......
  • 就业班 第二阶段 2401--3.29 day9 shell之正则+数组
    九、shell编程-数组普通数组:只能用整数作为数组的索引关联数组:可以使用字符串作为数组的索引数组定义普通数组定义:[root@newrainshell]#books=(linuxshellawksed) 引用:[root@newrainshell]#echo${books[0]}linux[root@newrainshell]#echo${books......
  • 蓝桥杯javaB组备赛
    15届蓝桥杯备赛java语法基础IO框架importjava.util.*;importjava.IO.IOException;importjava.IO.BufferedReader;publicclassMain{publicstaticvoidmain(String[]args)throwsIOException{BufferedReaderreader=newBufferedReader(newInputStre......