递归
定义:自己调用自己
int f(int n){
....
f(n)
}
例如:斐波那契数列
1、2、3、5、8、13···
int f(int n)
{
if(n==1) return 1;
else if(n==2) return 2;
else return f(n-2)+f(n-1);
}
AcWing 推荐题库:
1~n:每个数字有选择或者不选两个方案;
方案的数量就为 n*2^n,数据范围在15之内,即15*2^15,思路:递归树
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=15;
int n;
int st[N]; //状态,记录每个位置当前的状态,0表示还没考虑,1表示选他,2表示不选他
void dfs(int u)
{
if( u>n ) {
for(int i=1;i<=n;i++)
{
if(st[i]==1) printf("%d ",i);
}
printf("\n");
return;
}
st[u]=2;
dfs(u+1);//第一个分支不选
st[u]=0;//恢复现场
st[u]=1;
dfs(u+1);//第二个分支选
st[u]=0;//恢复现场
}
int main()
{
cin>>n;
dfs(1);
return 0;
}
93 递归实现组合型枚举
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 30;
int n,m;
int way[N];
void dfs(int u,int start)
{
if( u+n-start < m) return;//剪枝
if( u == m+1)
{
for(int i=1;i<=m;i++) printf("%d ",way[i]);
puts("");
return;
}
for(int i=start;i<=n;i++)
{
way[u]=i;
dfs(u+1,i+1);
way[u]=0;//恢复现场
}
}
int main()
{
scanf("%d%d",&n,&m);
dfs(1,1);
return 0;
}
94 递归实现排列型枚举
顺序1:依次枚举每个数放在哪个位置 ;
n个数放
顺序2:依次枚举每个位置哪个数。
递归搜索树,例如n=3,3个位置放三个数;
字典序最小,从小到大的进行输出,得到的字典序就是最小的;
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=10;
int n;
int state[N];//0表示还未放数,1~n代表放过哪个数字
bool used[N];//true表示用过,false表示还没用过
void dfs(int u)
{
if(u>n) //边界
{
for(int i=1;i<=n;i++) printf("%d ",state[i]); //打印方案
puts("");
return ;
}
//依次枚举每个分支,即当前位置可以填哪些数
for(int i=1;i<=n;i++)
{
if(!used[i])
{
state[u]=i;
used[i]=true;
dfs(u+1);
//恢复现场
state[u]=0;
used[i]=false;
}
}
}
int main()
{
scanf("%d",&n);
dfs(1);
return 0;
}
递推:
即通过已知条件,利用特定关系得出中间推论,直至得到结果的算法。
717 简单斐波那契
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int f[46];
f[1] = 0, f[2]=1;
for(int i=3;i<=n;i++)
f[i]=f[i-1]+f[i-2];
for(int i=1;i<=n;i++)
cout<<f[i]<<' ';
return 0;
}
116 飞行员兄弟
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
#define x first
#define y second
const int N=5;
typedef pair<int,int> PII;
char g[N][N],backup[N][N];
int get(int x,int y)
{
return x*4+y;
}
void turn_one(int x,int y)
{
if(g[x][y]=='-') g[x][y]='+';
else g[x][y]='-';
}
void turn_all(int x,int y)
{
for(int i=0;i<4;i++)
{
turn_one(x,i);
turn_one(i,y);
}
turn_one(x,y);
}
int main()
{
vector <PII> res;
for(int i=0;i<4;i++) cin>>g[i];
for(int op=0;op<1<<16;op++)
{
vector<PII> temp;
memcpy(backup,g,sizeof g); //备份
//进行操作
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
{
if(op>>get(i,j)&1){
temp.push_back({i,j});
turn_all(i,j);
}
}
//判断
bool has_closed=false;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++)
{
if(g[i][j]=='+') has_closed= true;
}
}
if(has_closed== false)
{
if(res.empty()||res.size()>temp.size()) res= temp;
}
memcpy(g,backup,sizeof g);//还原
}
cout<<res.size()<<endl;
for(auto op:res) cout<<op.x+1<<' '<<op.y+1<<endl;
return 0;
}
95 费解的开关95. 费解的开关 - AcWing题库
1208 翻硬币
#include<iostream>
#include<cstring>
using namespace std;
const int N=110;
int n;
char start[N],aim[N];
void turn(int i)
{
if(start[i]=='*') start[i]='o';
else start[i]='*';
}
int main()
{
cin>>start>>aim;
n=strlen(start);
int res=0;
for(int i=0;i<n-1;i++)
{
if(start[i]!=aim[i])
{
turn(i),turn(i+1);
res++;
}
}
cout<<res<<endl;
return 0;
}