AcWing 116. Hermanos piloto (sin recursividad cerebral)

tema

Esta pregunta no es adecuada para la recursividad, porque en las primeras preguntas, un interruptor se puede cambiar solo con un interruptor (el estado anterior se puede cambiar de lo siguiente, como: el interruptor inexplicable), pero el estado del interruptor superior en esta pregunta se puede cambiar desde el siguiente Cualquier cambio de interruptor.

Pensamiento: enumere todas las situaciones, porque esta pregunta puede ser violenta, y el código con una complejidad temporal de menos de 100 millones de
Inserte la descripción de la imagen aquí
contenedores vectoriales aumentará el tiempo de ejecución en 3 veces (compare el código total de y con el suyo y pruébelo tú mismo)

Aprenda a usar memcpy y sizeof

#include <cstring>//因为y总用的vector容器,我将他的代码进行了改变,蓝桥杯vector会有警告 
#include <iostream> 
#include <algorithm>
#include <cstdio>
using namespace std;

const int N = 5;

char g[N][N], backup[N][N];
int back[25][N];//back用于输出最后答案,每次发现步数少到都会复制到back中 

int get(int x, int y)
{
    
    
    return x * 4 + y;//将二维数组转换为一维,进行二进制操作 (与48行对应) 
}

void turn_one(int x, int y)
{
    
    
    if (g[x][y] == '+') g[x][y] = '-';//符号转化 
    else g[x][y] = '+';
}

void turn_all(int x, int y)
{
    
    
    for (int i = 0; i < 4; i ++ )
    {
    
    
        turn_one(x, i);
        turn_one(i, y);
    }

    turn_one(x, y);
}

int main()
{
    
    
    for (int i = 0; i < 4; i ++ ) cin >> g[i];

    int  cnt=0;
    for (int op = 0; op < 1 << 16; op ++ )// 1 << 16  表示为2的16次方 
    {
    
    
        int ans[25][N],k=0;
        
        memcpy(backup, g, sizeof g);        // 将g备份

        // 进行操作
        for (int i = 0; i < 4; i ++ )
            for (int j = 0; j < 4; j ++ )
                if (op >> get(i, j) & 1)//当二进制的位数为1时,需要操作 
                {
    
    
                    ans[k][0]=i;
					ans[k++][1]=j;
                    turn_all(i, j);
                }

        // 判断所有灯泡是否全亮
        bool has_closed = false;
        for (int i = 0; i < 4; i ++ )
            for (int j = 0; j < 4; j ++ )
                if (g[i][j] == '+')
                    has_closed = true;

        if (has_closed == false)
        {
    
    
            if (cnt==0 || cnt > k) {
    
    //当前的移动步数小于cnt时,将k赋值给cnt 
            	cnt = k;
            	 memcpy(back, ans, sizeof ans); //将ans数组复制给back 
			}
        }

        memcpy(g, backup, sizeof g);        // 还原g数组 
    }
    cout << cnt << endl;
    for(int i=0;i<cnt;i++)
    {
    
    
    	printf("%d %d\n",back[i][0]+1,back[i][1]+1);//数组需要加一(你懂!) 
	}

    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/qq_47874905/article/details/114914879
Recomendado
Clasificación