递归与递推(辅导课总结) 2021-12-29

递推

Acwing 95. 费解的开关

题目

在这里插入图片描述

思路

这题的大概思路有两个:dfs和递推。 如果使用dfs来做的话,可能会超时。
下面我们看看递推的大致思路:
首先我们这道题的目的是让每个灯都变亮,我们会发现其实每个灯之间都是有关系的,如果有一个灯不亮,那么他周围的灯就需要改变状态来让他变亮,但如果就这样思考的话,肯定不行,我们可以先把第一行固定下来,利用第一行的状态来递推下面几行的状态情况:首先第一行有5个灯,一共会有2^5也就是32种不同的状态,然后利用第二行和第一行的关系,去让第一行的灯全部变亮,这时第一行全部变亮了,之后再利用第三行与第二行的关系,让第二行全部变亮,以此类推,直到最后一行之前,我们都可以利用后一行与前一行的关系,让前一行变亮,但是最后一行已经没有后一行了,所有最后一行成为了判断是否全亮的标准,如果此时最后一行也是全部都亮的,那么就说明此时枚举的这种状态可以成功,但不一定是最简的,所有程序中要维护一个最小变量。

注意点

这里面有一个困扰我很久的地方:为什么是k>>i&1的时候进入if,不应该是灯不亮的时候进去if,然后利用turn函数让它变量吗?其实并不是这样的,这说明我对k还没有理解,k是用来枚举第一行的32种不同状态的,例如:如果k=0,换成5位的二进制也就是00000,这里的0表示状态不需要发生变化,如果k=1,二进制也就是00001,表示最后一个位置要发生变化。

代码

#include<iostream>
#include<cstring>
using namespace std;
const int N=6;
char p[N][N],temp[N][N];
int dx[5]={
   -1,1,0,0,0},dy[5]={
   0,0,-1,1,0};

void turn(int a,int b)
{
   
    for(int i=0;i<5;i++)
    {
   
        int na=a+dx[i],nb=b+dy[i];
        if(na<0||na>=5||nb<0||nb>=5) continue;
        else
        {
   
            p[na][nb]^=1; // 因为‘0’的阿斯克码为48,而1为49,只有一位不同,所有可以这么做。
        }
    }
}

int main()
{
   
    int t=0;
    cin>>t;
    while(t--)
    {
   
        for(int i=0;i<5;i++)
        {
   
            cin>>p[i];
        }
        
        int res=10;
        
        for(int k=0;k<32;k++)
        {
   
            int step=0;  //注意这个step要写在循环里面,因为针对每种情况step都要重新计算,以求出最小值。
            memcpy(temp,p,sizeof p);
            for(int i=0;i<5;i++)   //枚举第0行的32种不同的状态
            {
   
                if(k>>i&1)   //这里的k代表32种不同的状态,1表示与原来的状态不同,0表示与原来的状态相同
                {
   
                    step++;
                    turn(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个数学不怎么好的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值