蓝桥杯--递归与递推

92. 递归实现指数型枚举

从 1~n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。

输入格式
输入一个整数n。

输出格式
每行输出一种方案。

同一行内的数必须升序排列,相邻两个数用恰好1个空格隔开。

对于没有选任何数的方案,输出空行。

本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。

数据范围
1≤n≤15
输入样例:
3
输出样例:

3
2
2 3
1
1 3
1 2
1 2 3

#include 

using namespace std;

const int N = 15 + 3;

int n;
int st[N];      // 记录每个位置的状态,0表示还没考虑,1表示选它,2表示不选它

void dfs(int u){
    // 递归出口
    if(n == u) {
        for(int i = 0;i < n;i++){
            // 如果选了,则输出
            if(st[i] == 1) printf("%d ",i+1);
        }
        puts("");
        return;
    }
    
    st[u] = 2;
    dfs(u+1);   // 第一个分支,不选
    st[u] = 0;  // 恢复现场
    
    
    st[u] = 1;  // 第二个分支,选它
    dfs(u+1);	// 恢复现场
    st[u] = 0;
}


int main(){
    
    scanf("%d",&n);
    
    dfs(0);
    
    return 0;
    
}

94. 递归实现排列型枚举

把 1~n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序。

输入格式
一个整数n。

输出格式
按照从小到大的顺序输出所有方案,每行1个。

首先,同一行相邻两个数用一个空格隔开。

其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。

数据范围
1≤n≤9
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

#include 

using namespace std;

const int N = 9 + 1;

int n;

int path[N];    // 保存路径
bool st[N];     // 判断每个数是否被使用过了

void dfs(int u){
    // 递归边界
    if(u == n){
        for(int i = 0;i < n;i++){
            printf("%d ",path[i]);
        }
        puts("");
    }
    
    for(int i = 1;i <= n;i++){
        // 如果当前数字没用被使用过
        if(!st[i]){
            path[u] = i;
            st[i] = true;
            // 递归
            dfs(u+1);
            // 恢复现场
            path[u] = 0;
            st[i] = false;
        }
    }
}


int main(){
    scanf("%d",&n);
    
    dfs(0);
    
    return 0;
}

717. 简单斐波那契

以下数列0 1 1 2 3 5 8 13 21 …被称为斐波纳契数列。

这个数列从第3项开始,每一项都等于前两项之和。

输入一个整数N,请你输出这个序列的前N项。

输入格式
一个整数N。

输出格式
在一行中输出斐波那契数列的前N项,数字之间用空格隔开。

数据范围
0 输入样例:
5
输出样例:
0 1 1 2 3

在这里插入代码片

95. 费解的开关

你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。

我们用数字“1”表示一盏开着的灯,用数字“0”表示关着的灯。下面这种状态

10111
01101
10111
10000
11011
在改变了最左上角的灯的状态后将变成:

01111
11101
10111
10000
11011
再改变它正中间的灯后状态将变成:

01111
11001
11001
10100
11011
给定一些游戏的初始状态,编写程序判断游戏者是否可能在6步以内使所有的灯都变亮。

输入格式
第一行输入正整数n,代表数据中共有n个待解决的游戏初始状态。

以下若干行数据分为n组,每组数据有5行,每行5个字符。每组数据描述了一个游戏的初始状态。各组数据间用一个空行分隔。

输出格式
一共输出n行数据,每行有一个小于等于6的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。

对于某一个游戏初始状态,若6步以内无法使所有灯变亮,则输出“-1”。

数据范围
0 输入样例:
3
00111
01011
10001
11010
11100

11101
11101
11110
11111
11111

01111
11111
11111
11111
11111
输出样例:

3
2
-1

93. 递归实现组合型枚举

从 1~n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。

输入格式
两个整数 n,m ,在同一行用空格隔开。

输出格式
按照从小到大的顺序输出所有方案,每行1个。

首先,同一行内的数升序排列,相邻两个数用一个空格隔开。

其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如1 3 5 7排在1 3 6 8前面)。

数据范围
n>0 ,
0≤m≤n ,
n+(n−m)≤25
输入样例:
5 3
输出样例:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5

#include 

using namespace std;

const int N = 25 + 5;

int n,m;
int path[N];

void dfs(int u,int start){
    // 减枝
    if(u + n-start < m) return;
    
    if(u == m){
        for(int i = 0;i < m;i++) printf("%d ",path[i]);
        puts("");
        return;
    }
    for(int i = start;i < n;i++){
        path[u] = i + 1;
        dfs(u+1,i+1);
        path[u] = 0;        // 恢复现场
        
    }
}

int main(){
   scanf("%d%d",&n,&m);
   
   dfs(0,0);
   
   return 0;
}

1209. 带分数

100 可以表示为带分数的形式:100=3+69258714
还可以表示为:100=82+3546197
注意特征:带分数中,数字 1∼9 分别出现且只出现一次(不包含 0)。

类似这样的带分数,100 有 11 种表示法。

输入格式
一个正整数。

输出格式
输出输入数字用数码 1∼9 不重复不遗漏地组成带分数表示的全部种数。

数据范围
1≤N<106
输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6

1208. 翻硬币

小明正在玩一个“翻硬币”的游戏。

桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。

比如,可能情形是:oo*oooo

如果同时翻转左边的两个硬币,则变为:oooo***oooo

现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?

我们约定:把翻动相邻的两个硬币叫做一步操作。

输入格式
两行等长的字符串,分别表示初始状态和要达到的目标状态。

输出格式
一个整数,表示最小操作步数

数据范围
输入字符串的长度均不超过100。
数据保证答案一定有解。

输入样例1:


oo
输出样例1:
5
输入样例2:
ooo***
ooo***
输出样例2:
1

你可能感兴趣的:(#,蓝桥杯,算法,java,dfs,c语言)