ԅ(¯ㅂ¯ԅ)。436 2023-03-17 18:48 采纳率: 83.3%
浏览 43
已结题

关于递推费解的开关问题

费解的开关

25盏灯排成一个 5×5的方形。
每一个灯都有一个开关,游戏者可以改变它的状态。
每一步,游戏者可以改变某一个灯的状态。
游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
我们用数字 1表示一盏开着的灯,用数字 0 表示关着的灯。

输入格式
第一行输入正整数 n,代表数据中共有 n个待解决的游戏初始状态。
以下若干行数据分为 n组,每组数据有 5 行,每行 5 个字符。
每组数据描述了一个游戏的初始状态。
各组数据间用一个空行分隔。

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

数据范围
0<n≤500

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<stdlib.h>
const int N = 6;//每个字符串后面还有个\0
char g[N][N], backup[N][N];
void turn(int x, int y) {
    int dx[5] = {-1,1,0,0,0};
    int dy[5] = {0,0,-1,+1,0};
    for (int i = 0; i < 5; i++) {
        int a = x + dx[i];
        int b = y + dy[i];
        if(a<0||a>=5||b<0||b>=5) continue;   // 在边界外,直接忽略即可
        backup[a][b] ^= 1;
    }
    return;
}
int main() {
    int n;
    scanf("%d", &n);//几组
    int step=0;//记录步数
    while (n--) {
        for (int i = 0; i < 5; i++) {//输入每组
            scanf("%d", &g[i]);
        }
        for (int i = 0; i < 32; i++) {//第一行全排列有32种,每一种有5位
            memcpy(backup, g, sizeof g);//对g进行备份
            
            for (int j = 0; j < 5; j++) {//按第一行
                if ((i >> j & 1)==0) {//i >> j & 1 每一种全排列的第j位//0灭1开
                    step++;
                    turn(0, j);
                }
            }
            for (int p = 0; p < 4; p++) {//前4行
                for (int q = 0; q < 5; q++) {
                    if (backup[p][q] =='0' ) {
                        step++;
                        turn(p+1, q);
                    }
                }
            }
            for (int i = 0; i < 5; i++) {
                if (backup[4][i] == '0') {  step = -1; break; }

            }
        }
     if (step >= 6) step = -1;
     printf("%d", step);
    }
    return 0;
}

img


正确答案
3
2
-1

  • 写回答

1条回答 默认 最新

  • Leodong. 2023-03-17 19:23
    关注

    该回答引用GPTᴼᴾᴱᴺᴬᴵ,具体如下:

    这段代码中有几个问题需要解决:
    
    1.输入数据时,应该使用字符数组类型的g来保存,而不是整型数组。
    
    2.全排列的循环体应该放在第一行灯的开关状态改变后,而不是一开始就进行。
    
    3.判断灯是否全部亮起来,应该在所有情况的全排列循环结束之后再进行。
    
    4.在输出结果时,应该换行。
    
    5.每一次新的数据组开始前,都需要将step变量的值重新赋值为06.在循环的过程中,需要进行多次灯的状态改变,而不是只改变一次。
    
    

    下面是修改后的代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int N = 6;//每个字符串后面还有个\0
    char g[N][N], backup[N][N];
    
    void turn(int x, int y) {
        int dx[5] = {-1,1,0,0,0};
        int dy[5] = {0,0,-1,+1,0};
        for (int i = 0; i < 5; i++) {
            int a = x + dx[i];
            int b = y + dy[i];
            if(a<0||a>=5||b<0||b>=5) continue;   // 在边界外,直接忽略即可
            backup[a][b] ^= 1;
        }
        return;
    }
    
    int bfs()
    {
        int step=0;//记录步数
        for (int i = 0; i < 32; i++)//第一行全排列有32种,每一种有5位
        {
            memcpy(backup, g, sizeof g);//对g进行备份
    
            for (int j = 0; j < 5; j++)//按第一行
            {
                if ((i >> j & 1)==0)//i >> j & 1 每一种全排列的第j位//0灭1开
                {
                    step++;
                    turn(0, j);
                }
            }
    
            for (int p = 0; p < 4; p++)//前4行
            {
                for (int q = 0; q < 5; q++)
                {
                    if (backup[p][q] =='0')
                    {
                        step++;
                        turn(p+1, q);
                    }
                }
            }
    
            bool flag = true;
            for (int j = 0; j < 5; j++)
                if (backup[4][j] == '0') {flag = false; break;}
            if (flag) return step;
            if (step >= 6) return -1;
        }
        return -1;
    }
    
    int main()
    {
        int n;
        scanf("%d", &n);//几组
        while (n--) 
        {
            for (int i = 0; i < 5; i++)//输入每组
                scanf("%s", g[i]);
            int res = bfs();
            printf("%d\n", res);
        }
        return 0;
    }
    
    
    修改说明:
    
    1、将头文件 stdlib.h 改为 algorithm,并且加上命名空间 std,避免在调用 memcpy 函数时出现错误。
    2、将 step 的定义放到 bfs 函数中,每次调用 bfs 都会重新定义一个 step,避免出现每组数据的步数计算混乱的情况。
    3、将检查是否已经全部点亮的语句放在 bfs 函数中,这样可以让代码更加简洁易懂。
    4、将输入 g[i] 的方式改为 scanf("%s", g[i]),这样可以简化输入代码,并且避免出现每组数据最后一行多读取一个换行符的问题。
    

    如果以上回答对您有所帮助,望采纳~谢谢

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月18日
  • 已采纳回答 3月18日
  • 创建了问题 3月17日

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。