代码并非全部为本人原创,仅提供整理作用;
不是蓝桥杯的题目会提供全部内容;
一. 暴力枚举
1.直接枚举( for+if )
2.递归枚举法(dfs):
模板:
void dfs(参数){
if(终止条件){搜集结果;return;}
for(单层所有元素){
(不可使用的元素剪枝)continue;
标记;
递归(参数+1);
取消标记;} }
如果要不断比较,更新结果则要不断回溯 vis[i]=0;
地图一般不回溯;
(1)全排列:给定一个数字n,请按照字典序输出排列[1,2,...,n]的全排列。
dfs里for遍历完之后回到上一个dfs的位置。
#include<bits/stdc++.h>
using namespace std;
const int N=15;
int a[N];
bool vis[N];
void dfs(int dep,int n){
if(dep==n+1){
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
cout<<endl;
return;
}
for(int i=1;i<=n;i++){
if(vis[i])continue;
vis[i]=1;
a[dep]=i;
dfs(dep+1,n);
vis[i]=0;
}
}
int main(){
int n;cin>>n;
dfs(1,n);
return 0;
}
最大数字:进制问题/贪心/回溯
#include <bits/stdc++.h>
using namespace std;
string n;
long long ans;
int a,b;
void dfs(int x,long long an){
int t=n[x]-'0';
if(!n[x]){ ans=max(ans,an);
return;}
int c=min(a,9-t);
a-=c;
dfs(x+1,an*10+t+c);
a+=c;
if(b>t){
b=b-t-1;
dfs(x+1,an*10+9);
b=b+t+1;
}
}
int main(){
cin>>n>>a>>b;
dfs(0,0);
cout<<ans;
return 0;
}
(2) 最大连通: DFS与连通性
#include<bits/stdc++.h>
using namespace std;
char g[35][65];
int a[4][2]={0,1,0,-1,1,0,-1,0};
int vis[35][65]={0};
int ans=0;
int sum=0;
void dfs(int x,int y){
if(x<0||x>29||y<0||x>59||g[x][y]!='1'||vis[x][y])return;
sum++;
vis[x][y]=1;
for(int i=0;i<4;i++){
int tx=x+a[i][0];
int ty=y+a[i][1];
if(tx>=0&&ty>=0&&tx<=29&&ty<=59&&g[tx][ty]=='1'&&vis[tx][ty]==0){
dfs(tx,ty);}
}
ans= max(ans,sum);
}
int main(){
for(int i=0;i<30;i++){
for(int j=0;j<60;j++){
cin>>g[i][j];
}
}
for(int i=0;i<30;i++){
for(int j=0;j<60;j++){
sum=0;
if(g[i][j]=='1'){//不是需要的元素不进入if;
dfs(i,j);
}
}
}
cout<<ans;
return 0;
}
(3)小朋友崇拜圈:闭环问题
(有1234隐形序列)
#include <iostream>
using namespace std;
int a[100005];
int vis[100005];
int m,t;
void dfs(int x,int ans){
if(vis[x]){if(x==t){//第一个回到的点是自己,则为环;
if(ans>m)m=ans;//如果为环,则进行大小判断传入结果,无则直接return;
}return;
}
vis[x]=1;//标记;
dfs(a[x],ans+1);//a[x]为指向的元素,ans为已走的步数;
vis[x]=0;//回溯;
}
int main(){
int n;cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];//i表示自己,a[i]表示指向的元素;
}
for(int i=1;i<=n;i++){
t=i;//用临时变量保存自己,该变量为全局变量;
dfs(i,0);
}cout<<m;
return 0;
}
(4)正则问题:分组计数用dfs
#include <bits/stdc++.h>
using namespace std;
string s;
int k=0;
int dfs(){
int res=0;//递归的res不断初始化为0;
while(k<s.size()){
if(s[k]=='('){
k++;//索引先行;
res += dfs();//只要括号未结束就会一直在递归中,直到输出结果;
k++;//跳过')',使得k>=s.size,结束循环;
}
else if(s[k]=='|'){
k++;
res=max(res,dfs());
}
else if(s[k]==')'){
break;//break跳出函数,执行下一句,return出dfs的结果;
}
else {
k++;
res++;//什么都没有直接res+1;
}
}
return res;
}
int main()
{
cin>>s;
cout<<dfs()<<endl;
return 0;
}
二.并查集
(1)无优化:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100009;
int pre[N];//父节点(根节点)
int root(int x){//用递归查找根节点
return pre[x]==x?x:root(pre[x]);
}
void merge (int x,int y){//用一条节点的根节点连到另一个节点,表合并操作
x=root(x);y=root(y);
if(x==y)return;//若已经同根相连,即已连通,return即可
pre[x]=y;//pre[y]=x;两个点都可
}
void solve(){
int n,m;cin>>n>>m;
for(int i=1;i<=n;++i)pre[i]=i;//初始化:自己是自己的根节点
while(m--){
int op,x,y;cin>>op>>x>>y;
if(op==1)merge(x,y);
else cout<<(root(x)==root(y)?"Y":"N")<<"\n";//用三目运算符输出需用()
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//取消同步流,提高速度,未优化的速度极慢
int _ =1;
while( _ --)solve();
return 0;
}
【一】+【二】+邻接表:
发现环:
#include<bits/stdc++.h>
using namespace std;
int p[100050],vis[100050],ans[100050];
int n,a,b;
int s,en;//dfs (start end)
vector<int>e[100050];//edge
int root(int x){return p[x]==-1?x:p[x]=root(p[x]);}
void pr(int step)//排序输出
{
sort(ans+1,ans+1+step);//ans[0]=0;
for(int i=1;i<=step;i++)cout<<ans[i]<<" ";
}
void dfs(int x,int step)
{
vis[x]=1;//sign
ans[step]=x;
if(x==en){pr(step);return;}
for(int i=0;i<e[x].size();i++){
if(!vis[e[x][i]])dfs(e[x][i],step+1);}
//4的邻接点是2,2不满足if,
//循环结束回到上一节点2的另一种可能1,同一层step的结果覆盖;
}
int main()
{
memset(p,-1,sizeof(p));//初始化
cin>>n;
while(n--){
cin>>a>>b;
if(root(a)==root(b))s=a,en=b;
else {
p[root(b)]=a;//merge
e[a].push_back(b);//edge
e[b].push_back(a);
}
}
dfs(s,1);
return 0;
}
三.排序算法
1.sort函数
数组和指针用sort(a+n,a+m);//end要比实际多出一位;
STL容器用迭代器sort(a.begin(),a.end());
#include <bits/stdc++.h>
using namespace std;
int a[500086];
bool cmp(int x,int y){
return x>y;
}
//struct cmp2(){
//bool operator()(char a,char b){
//return a>b;}
int main()
{
int n;
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++)cout<<a[i]<<" ";
cout<<"\n";
sort (a+1,a+n+1,cmp);
//sort (a+1,a+n+1,cmp2());struct要加括号;
//sort (a+1,a+n+1,greater());直接写STL的库函数,降序函数;
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
return 0;
}
四.数学算法
你不干?有的是帕鲁干!(小白赛);
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
int main(){
long long n,x,a,b,k;
cin>>n;
while(n--){
cin>>x;
if(x%8==0 && x>0){
cout<<"Yes"<<endl;
k=x/4;
a=k-1;
b=k+1;
cout<<a<<" " <<b<<endl;
}else cout<<"No" <<endl;
}return 0;
}
五.堆/优先队列
#include<bits/stdc++.h>
using namespace std;
int main(){
int q;cin>>q;
priority_queue<int>pq;
long long x,sum=0;
while(q--){
int op;cin>>op;
if(op==1){
cin>>x;
sum+=x;
pq.push(x);
}
else if(op==2){
if(pq.size()){
sum-=pq.top();
pq.pop();
}}
}cout<<sum<<endl;
return 0;
}