蓝桥杯训练 | 递归与递推 | 01
递归实现指数型枚举
#include<iostream>
using namespace std;
const int N=15+10;
bool st[N];
int n;
void dfs(int u){
if(u>n){
for(int i=1;i<=n;i++){
if(st[i])cout << i << " ";
}
cout << endl;
return;
}
st[u]=true,dfs(u+1);
st[u]=false,dfs(u+1);
}
int main(){
cin >> n;
dfs(1);
return 0;
}
递归实现排列型枚举
#include<bits/stdc++.h>
using namespace std;
const int N=9+10;
bool used[N];
vector<int> path;
int n;
int choice[] = {1,2,3,4,5,6,7,8,9};
void dfs(int u){
if(u==n){
for(vector<int>::iterator i=path.begin();i!=path.end();i++)
cout << *i << " ";
cout << endl;
return ;
}
for(int i=0;i<n;i++){
if(!used[i]){
used[i]=true,path.push_back(choice[i]);
dfs(u+1);
used[i]=false,path.pop_back();
}
}
}
int main(){
cin >> n;
dfs(0);
return 0;
}
简单斐波那契
#include<iostream>
using namespace std;
const int N=46+10;
int q[N];
int main(){
int n;
cin >> n;
q[0]=0,q[1]=1;
for(int i=2;i<n;i++)q[i]=q[i-1]+q[i-2];
for(int i=0;i<n;i++)cout << q[i] << " ";
cout << endl;
return 0;
}
费解的开关
第一行的状态是通过枚举确定的,然后通过第一行的状态来确定下面行的状态,依次类推.
核心: 第一行的操作确定后,第二行的操作也就唯一确定.
#include<bits/stdc++.h>
using namespace std;
const int N=6;
char g[N][N],backup[N][N];
int dx[]={0,1,0,-1,0};
int dy[]={-1,0,1,0,0};
void turn(int x,int y){
for(int i=0;i<5;i++){
int tx=x+dx[i],ty=y+dy[i];
if(tx<0 || tx>=5 || ty<0 || ty>=5)continue;
g[tx][ty]=g[tx][ty]=='0'?'1':'0';
}
}
int main(){
int T;
cin >> T;
while(T--){
for(int i=0;i<5;i++)cin>>g[i];
int res=1<<30;
for(int op=0;op<(1<<5);op++){
memcpy(backup,g,sizeof g);
int step=0;
for(int i=0;i<5;i++){
if(op >> i & 1){
turn(0,i),step++;
}
}
for(int i=1;i<5;i++){
for(int j=0;j<5;j++){
if(g[i-1][j]=='0'){
turn(i,j),step++;
}
}
}
bool success=true;
for(int i=0;i<5;i++)
if(g[4][i]=='0'){
success=false;
break;
}
if(success && step<=6)res=min(step,res);
memcpy(g,backup,sizeof g);
}
if(res==1<<30)cout << "-1" << endl;
else cout << res << endl;
}
return 0;
}
递归实现组合型枚举
#include<bits/stdc++.h>
using namespace std;
const int N= 30;
int n,m;
int choice[N];
vector<int> path;
bool used[N];
void dfs(int u,int s){
if(u+n-s<m)return;
if(u==m){
for(int i=0;i<path.size();i++)cout << path[i] << " ";
cout << endl;
return;
}
for(int i=s;i<n;i++){
if(!used[i]){
used[i]=true,path.push_back(choice[i]);
dfs(u+1,i+1); // 坑
used[i]=false,path.pop_back();
}
}
}
int main(){
cin >> n >> m;
for(int i=0;i<=n;i++)choice[i]=i+1;
dfs(0,0);
return 0;
}
带分数
#include<bits/stdc++.h>
using namespace std;
int n,res;
int choice[]={1,2,3,4,5,6,7,8,9};
vector<int> path;
bool used[20];
int cal(int l,int r){
int res=0;
for(int i=l;i<=r;i++)res=res*10+path[i];
return res;
}
void dfs(int u){
if(u==9){
for(int i=0;i<7;i++){
for(int j=i+1;j<8;j++){
int a = cal(0,i);
int b = cal(i+1,j);
int c = cal(j+1,8);
if(c*(n-a)==b)res++;
}
}
return;
}
for(int i=0;i<9;i++){
if(!used[i]){
used[i]=true,path.push_back(choice[i]);
dfs(u+1);
used[i]=false,path.pop_back();
}
}
}
int main(){
cin >> n;
dfs(0);
cout << res << endl;
return 0;
}
飞行员兄弟
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=5;
char g[N][N],backup[N][N];
bool check(){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(g[i][j]=='+')return false;
}
}
return true;
}
void turn(int x,int y){
for(int i=0;i<4;i++){
g[x][i]=g[x][i]=='+'?'-':'+';
g[i][y]=g[i][y]=='+'?'-':'+';
}
g[x][y]=g[x][y]=='+'?'-':'+';
}
int main(){
for(int i=0;i<4;i++)cin>>g[i];
vector<PII> res_f;
for(int op=0;op< (1<<16);op++){
vector<PII> res_t;
memcpy(backup,g,sizeof g);
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(op >> (i*4+j) & 1){
turn(i,j);
res_t.push_back({i,j});
}
}
}
if(check()){
if(res_f.empty() || res_f.size() > res_t.size())res_f=res_t;
}
memcpy(g,backup,sizeof g);
}
cout << res_f.size() << endl;
for(vector<PII>::iterator i=res_f.begin();i!=res_f.end();i++)
cout << i->first + 1 << " " << i->second + 1<< endl;
return 0;
}
翻硬币
#include<bits/stdc++.h>
using namespace std;
const int N=110;
char g[N],dest[N],backup[N];
void turn(int x){
g[x]=g[x]=='*'?'o':'*';
g[x-1]=g[x-1]=='*'?'o':'*';
}
int main(){
cin >> g >> dest;
int len = strlen(g);
int res_f=1<<30;
for(int op=0;op<2;op++){ // 枚举第一个位置按还是不按
int res_t=0;
memcpy(backup,g,sizeof g);
if(op){ // 按
g[0]=g[0]=='*'?'o':'*';
res_t++;
for(int i=1;i<len;i++){
if(g[i-1]!=dest[i-1]){
res_t++;
turn(i);
}
}
if(g[len-1]==dest[len-1] && res_f > res_t)res_f=res_t;
}else{
for(int i=1;i<len;i++){
if(g[i-1]!=dest[i-1]){
res_t++;
turn(i);
}
}
if(g[len-1]==dest[len-1] && res_f > res_t)res_f=res_t;
}
memcpy(g,backup,sizeof g);
}
cout << res_f << endl;
return 0;
}