目前,这一章都已经熟练掌握了。
目录
在用递归的时候可以先画一个递归树来分析。
92. 递归实现指数型枚举 【板子题】
#include<bits/stdc++.h>
using namespace std;
int a[30],vis[30],n;
void dfs(int index)
{
if(index==n)
{
for(int i=0;i<n;i++) if(vis[i]==1) cout<<i+1<<" ";
cout<<endl;
return;
}
vis[index]=1;//选
dfs(index+1);
vis[index]=0;//不选
dfs(index+1);
}
int main(void)
{
cin>>n;
dfs(0);
return 0;
}
注意: 递归一定要恢复现场。
94. 递归实现排列型枚举 【板子题】
#include<cstdio>
#include<iostream>
int state[10];//0代表还没有选数,1~n代表放了哪个数
bool m[10];//true表示用过,false表示没有用过
int n;
void dfs(int u)//第几个位置
{
if(u==n)
{
for(int i=0;i<n;i++)
{
printf("%d ",state[i]);
}
printf("\n");
return;
}
for(int i=1;i<=n;i++)//枚举所有的数,看哪个可以选
{
if(!m[i])//该数没有被选
{
m[i]=true;//状态表示选了
state[u]=i;//选这该数
dfs(u+1);//开始选下一个位置
m[i]=false;//恢复现场
state[u]=0;//恢复现场
}
}
}
int main(void)
{
scanf("%d",&n);
dfs(0);
return 0;
}
可以用现有的函数实现全排列
#include<cstdio>
#include<algorithm>
using namespace std;
int a[10]={1,2,3,4,5,6,7,8,9};
int main(void)
{
int n;
scanf("%d",&n);
do
{
for(int i=0;i<n;i++)
{
printf("%d ",a[i]);
}
printf("\n");
}while(next_permutation(a,a+n));
return 0;
}
93. 递归实现组合型枚举【板子题】
题目详解
代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int m,n;
int ways[30];
void dfs(int u,int start)//u 代表当前是第几位 start表示选的数从哪里开始遍历
{
if(u==m+1)//选够了
{
for(int i=1;i<=m;i++)
{
printf("%d ",ways[i]);
}
puts("");//回车,这是一种比printf() 简单的写法
return;
}
for(int i=start;i<=n;i++)//枚举元素
{
ways[u]=i;
dfs(u+1,i+1);
ways[u]=0;//恢复现场
}
}
int main(void)
{
cin>>n>>m;
dfs(1,1);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int a[30],vis[30],n,m;
void dfs(int index,int start)
{
if(index==m)
{
for(int i=0;i<m;i++) cout<<a[i]<<" ";
cout<<endl;
return;
}
for(int i=start;i<=n;i++)
{
if(!vis[i])
{
a[index]=i;
vis[i]=1;
dfs(index+1,i);
vis[i]=0;
}
}
}
int main(void)
{
cin>>n>>m;
dfs(0,1);
return 0;
}
717. 简单斐波那契 【简单 / 递推】
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
typedef long long int LL;
LL a[N],n;
int main(void)
{
cin>>n;
a[1]=0,a[2]=1;
for(int i=3;i<=n;i++) a[i]=a[i-1]+a[i-2];
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
return 0;
}
95. 费解的开关 【二进制枚举 / 递推】
#include<bits/stdc++.h>
using namespace std;
int a[30][30],b[30][30],n;
int dx[5]={0,-1,0,1,0};
int dy[5]={0,0,1,0,-1};
void turn(int x,int y)
{
for(int i=0;i<5;i++)
{
int tempx=x+dx[i];
int tempy=y+dy[i];
if(tempx>=0&&tempx<5&&tempy>=0&&tempy<5) b[tempx][tempy]^=1;
}
}
int dfs()
{
int ans=10;
for(int k=0;k<32;k++)
{
int cnt=0;
memcpy(b,a,sizeof b);
for(int i=0;i<5;i++) if(k>>i&1) turn(0,i),cnt++;
for(int i=1;i<5;i++)
for(int j=0;j<5;j++) if(!b[i-1][j]) turn(i,j),cnt++;
bool flag=true;
for(int i=0;i<5;i++) if(!b[4][i]) flag=false; //判断最后一排是不是都是亮的
if(flag) ans=min(ans,cnt);
}
if(ans>6) return -1;
else return ans;
}
int main(void)
{
cin>>n;
while(n--)
{
string s[10];
for(int i=0;i<5;i++) cin>>s[i];
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
a[i][j]=s[i][j]-'0';
cout<<dfs()<<endl;
}
return 0;
}
1208. 翻硬币 【递推】
#include<bits/stdc++.h>
using namespace std;
string a,b;
int main(void)
{
cin>>a>>b;
int ans=0;
for(int i=1;i<b.size();i++)
{
if(b[i-1]!=a[i-1])
{
b[i-1]=a[i-1];
if(b[i]=='*') b[i]='o';
else b[i]='*';
ans++;
}
}
cout<<ans;
return 0;
}
116. 飞行员兄弟 【二进制枚举 】
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int a[10][10],b[10][10];
void turn(int x,int y)
{
for(int i=0;i<4;i++) b[x][i]^=1,b[i][y]^=1;
b[x][y]^=1;//按了两次得再按一次
}
int main(void)
{
string s[10];
for(int i=0;i<4;i++) cin>>s[i];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(s[i][j]=='+') a[i][j]=0;
else a[i][j]=1;
vector<PII> ans;
for(int i=0;i<(1<<16);i++)
{
vector<PII>temp;
memcpy(b,a,sizeof a);
for(int j=0;j<16;j++)
{
if( (i>>j) & 1 )
{
turn(j/4,j%4);
temp.push_back({j/4,j%4});
}
}
bool flag=true;
for(int j=0;j<4;j++)
for(int k=0;k<4;k++)
if(!b[j][k]) flag=false;
if(flag && ( ans.size()>temp.size() || ans.empty() ) ) ans=temp;
}
cout<<ans.size()<<endl;
for(auto op: ans) cout<<op.first+1<<" "<<op.second+1<<endl;
return 0;
}
1209. 带分数 【枚举】
#include<bits/stdc++.h>
using namespace std;
int a[10],ans;
int get(int l,int r)
{
int sum=0;
for(int i=l;i<=r;i++) sum=sum*10+a[i];
return sum;
}
int main(void)
{
int n; cin>>n;
for(int i=1;i<=9;i++) a[i]=i;
do
{
for(int i=1;i<=7;i++)
{
for(int j=i+1;j<=8;j++)
{
int a=get(1,i);
if(a>n) continue;
int b=get(i+1,j);
int c=get(j+1,9);
if(b%c==0&&a+b/c==n) ans++;
}
}
}while(next_permutation(a+1,a+10));
cout<<ans;
return 0;
}
acwing会TLE 其它oj可以过
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
int n;
string s="123456789";
int main(void)
{
cin>>n;
int cnt=0;
do
{
for(int i=1;i<=7;i++)
{
int a=stoi(s.substr(0,i));
if(a>n) continue;
for(int j=1;j<=8-i;j++)
{
int b=stoi(s.substr(i,j));
int c=stoi(s.substr(i+j));
if(b%c!=0) continue;
else
{
if(a+b/c==n) cnt++;
}
}
}
}while(next_permutation(s.begin(),s.end()));
printf("%d\n",cnt);
return 0;
}