【递归与递推 4】AcWing95. 费解的开关 、AcWing 93. 递归实现组合型枚举、AcWing 1209. 带分数、AcWing 1208. 翻硬币

简介: 【递归与递推 4】AcWing95. 费解的开关 、AcWing 93. 递归实现组合型枚举、AcWing 1209. 带分数、AcWing 1208. 翻硬币

AcWing95. 费解的开关

Description

你玩过“拉灯”游戏吗?


2525 盏灯排成一个 5×55×5 的方形。


每一个灯都有一个开关,游戏者可以改变它的状态。


每一步,游戏者可以改变某一个灯的状态。


游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。


我们用数字 11 表示一盏开着的灯,用数字 00 表示关着的灯。


下面这种状态

10111
01101
10111
10000
11011

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

01111
11101
10111
10000
11011

再改变它正中间的灯后状态将变成:

01111
11001
11001
10100
11011

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


输入格式

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


以下若干行数据分为 n 组,每组数据有 5 行,每行 5 个字符。


每组数据描述了一个游戏的初始状态。


各组数据间用一个空行分隔。


输出格式

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

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

数据范围

0 < n ≤ 500

输入样例:

3
00111
01011
10001
11010
11100
11101
11101
11110
11111
11111
01111
11111
11111
11111
11111

输出样例:

3
2
-1
难度:中等
时/空限制:1s / 256MB
总通过数:24338
总尝试数:39223
来源:《算法竞赛进阶指南》
算法标签

AcCode

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 6;
char g[N][N], backup[N][N];
int dx[5] = {-1, 0, 1, 0, 0}, dy[5] = {0, 1, 0, -1, 0};
void turn(int x, int y)
{
    for (int i = 0; i < 5; i ++ )
    {
        int a = x + dx[i], b = y + dy[i];
        if (a < 0 || a >= 5 || b < 0 || b >= 5) continue;   // 在边界外,直接忽略即可
        g[a][b] ^= 1;
    }
}
int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        for (int i = 0; i < 5; i ++ ) cin >> g[i];
        int res = 10;
        //二进制数中1表示要按,0表示不按
        for (int op = 0; op < 1 << 5; op ++ ) //32中方案(op代表的不是灯状态,而是按或者不按)
        {
            memcpy(backup, g, sizeof g);
            int step = 0;
            for (int i = 0; i < 5; i ++ )
                if (op >> i & 1)
                {
                    step ++ ;
                    turn(0, i);
                }
            for (int i = 0; i < 4; i ++ )
                for (int j = 0; j < 5; j ++ )
                    if (g[i][j] == '0')
                    {
                        step ++ ;
                        turn(i + 1, j);
                    }
            bool dark = false;
            for (int i = 0; i < 5; i ++ )
                if (g[4][i] == '0')
                {
                    dark = true;
                    break;
                }
            if (!dark) res = min(res, step);
            memcpy(g, backup, sizeof g);
        }
        if (res > 6) res = -1;
        cout << res << endl;
    }
    return 0;
}

AcWing 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 <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);
    //第一个i表示当前从第一位开始枚举,第二个1表示可以从1枚举
    dfs(1, 1);
    return 0;
}

AcWing 1209. 带分数

100 可以表示为带分数的形式:100=3+69258/714

还可以表示为:100=82+3546/197

注意特征:带分数中,数字 1∼9分别出现且只出现一次(不包含 0)。

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

输入格式

一个正整数。

输出格式

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

数据范围

输入样例1:

100

输出样例1:

11

输入样例2:

105

输出样例2:

6
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10;
int n;
bool st[N], backup[N];
int ans;
bool check(int a, int c)
{
    long long b = n * (long long)c - a * c;
    if (!a || !b || !c) return false;
    memcpy(backup, st, sizeof st);
    while (b)
    {
        int x = b % 10;     // 取个位
        b /= 10;    // 个位删掉
        if (!x || backup[x]) return false;
        backup[x] = true;
    }
    for (int i = 1; i <= 9; i ++ )
        if (!backup[i])
            return false;
    return true;
}
void dfs_c(int u, int a, int c)
{
    if (u > 9) return;
    if (check(a, c)) ans ++ ;
    for (int i = 1; i <= 9; i ++ )
        if (!st[i])
        {
            st[i] = true;
            dfs_c(u + 1, a, c * 10 + i);
            st[i] = false;
        }
}
void dfs_a(int u, int a)
{
    if (a >= n) return;
    if (a) dfs_c(u, a, 0);
    for (int i = 1; i <= 9; i ++ )
        if (!st[i])
        {
            st[i] = true;
            dfs_a(u + 1, a * 10 + i);
            st[i] = false;
        }
}
int main()
{
    cin >> n;
    dfs_a(0, 0);
    cout << ans << endl;
    return 0;
}

AcWing 1208. 翻硬币

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


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


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


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


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


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


输入格式

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


输出格式

一个整数,表示最小操作步数


数据范围

输入字符串的长度均不超过100。

数据保证答案一定有解。

输入样例1:

**********
o****o****

输出样例1:

5

输入样例2:

*o**o***o***
*o***o**o***

输出样例2:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 100;
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 ;i ++)
        if(start[i] != aim[i] )
        {
            turn(i),turn(i + 1);
            res ++ ;
        }
    cout << res << endl;
    return 0;
}
相关文章
|
5月前
|
存储
【洛谷 P1255】数楼梯 题解(递归+记忆化搜索+高精度)
这是一个使用动态规划解决的“数楼梯”问题。给定楼梯数`N`,求不同上楼方式的数量。程序通过递归函数`f()`计算,其中`f(x) = f(x - 1) + f(x - 2)`,初始条件`f(1) = 1`,`f(2) = 2`。考虑到数据规模可能很大,使用了高精度加法运算。样例输入`4`,输出`5`。代码中定义了一个存储中间结果的向量`mem`,并提供了一个用于显示高精度数的`printv()`函数。
75 0
|
6月前
|
算法
动态规划之第 N 个泰波那契数/三步问题【leetCode】【算法】
动态规划之第 N 个泰波那契数/三步问题【leetCode】【算法】
|
12月前
LeetCode题:70爬楼梯,126斐波那契数
LeetCode题:70爬楼梯,126斐波那契数
54 0
|
人工智能 移动开发 机器人
蓝桥杯AcWing 题目题解 - 二分与前缀和、差分
蓝桥杯AcWing 题目题解 - 二分与前缀和、差分
149 0
蓝桥杯AcWing 题目题解 - 递归与递推
蓝桥杯AcWing 题目题解 - 递归与递推
|
机器学习/深度学习 算法 C++
(C/C++)STL函数(3)二分算法题以及二分模板 和(蓝桥杯)递推与递归题目及解法(ACwing)
(C/C++)STL函数(3)二分算法题以及二分模板 和(蓝桥杯)递推与递归题目及解法(ACwing)
(C/C++)STL函数(3)二分算法题以及二分模板 和(蓝桥杯)递推与递归题目及解法(ACwing)
(蓝桥杯)递推与递归,前缀和,二分经典例题分析
(蓝桥杯)递推与递归,前缀和,二分经典例题分析
(蓝桥杯)递推与递归,前缀和,二分经典例题分析
蓝桥杯第十三讲--树状数组与线段树【例题】(二)
蓝桥杯第十三讲--树状数组与线段树【例题】
138 0
蓝桥杯第十三讲--树状数组与线段树【例题】(二)
|
算法 C++
蓝桥杯第十三讲--树状数组与线段树【例题】(一)
蓝桥杯第十三讲--树状数组与线段树【例题】
166 0
蓝桥杯第十三讲--树状数组与线段树【例题】(一)
牛客-合并回文子串(区间DP)
牛客-合并回文子串(区间DP)
180 0