算法 3.解谜问题

问题描述

在这里插入图片描述

输入

在这里插入图片描述

输出

在这里插入图片描述

测试用例

在这里插入图片描述

代码

这大概是学期内的第一道正经算法题了吧,枚举所有情况很明显超时也费空间
这个题的思路就是只枚举第一行的情况,再根据第一行的情况去推理剩下行的情况。
我没记错的话在B站上是有视频讲解类似题目的,是北大的课

#include<stdio.h>  //这是第三题 解谜游戏 
int main()  
{  //首先这道题一个最基本的点就是暴力枚举是肯定行不通的
   //参考了北京大学 算法基础的熄灯问题 进行局部枚举 
     int w,l;  
     scanf("%d %d",&w,&l);   
     int i,r,c;  
     int press[18][18] = {},now[18][18] = {};   // 这样初始化即可   
     long long int light;   
     int min = 1e8;  
	 
	 for(r = 1; r < w + 1; r ++)  
	 {  
	      scanf("%lld",&light);  
	      for(c = 1; c <= l; c ++)  
	      {    
	          now[r][c] = (light% 10);    
	          light /= 10;    
	      }    
	  } //将每行灯的状态录入,因为灯的左右相反并没有关系,所以不多做处理 
     long int m = 1;  
	 
	 for(int p = 1; p <= l; p ++)  
	 { 
	 	m = m * 2; 
	 }  //计算枚举第一行一共有多少种情况 
	 
	 for(int q = 1; q <= m; q ++)   
	 {  
	  	int p = 0;  
	  	int sum = 0;  
	    for(int a = 1; a < w; a ++)  
	        for(int b = 1 ; b < l + 1;b ++)  //在第一行固定的情况下,按照本行按按钮的情况和灯的情况推断下一行 
	            press[a + 1][b]=(now[a][b] + press[a][b] + press[a - 1][b] + press[a][b - 1] + press[a][b + 1]) % 2;  
	    
	    for(int c = 1; c < l + 1; c ++)  //最后根据前面给定的情况,判断在这种第一行的情况下,我们可不可以熄灭全部的灯 
	    {   
	        if((press[w][c - 1] + press[w][c] + press[w][c + 1] + press[w - 1][c]) % 2 != now[w][c])  
	        {  
	            p = -1;  
	            break;
	        }  
	        else  
	        {  
	            p = 1;  
	        }  
	    }  
	    
	    if(p == 1)  //如果可以,记录这种情况下需要按按钮的次数 
	    {  
	        for(r = 1; r < w + 1; r ++)  
	            for(c = 1; c < l + 1; c ++)  
	                if(press[r][c] == 1)  
	                { 
	                	sum = sum + 1;  
	                }  
	            
	            if(min == 0)  
	            {  
	                min=sum;  
	            }  
	            if(min != 0 && min > sum)  
	            {  
	                min=sum;  
	            }  
	    }  
	  	
	  	press[1][1]++;  //迭代第一行的每种状态 
	    c = 1;  
	    while(press[1][c] > 1)
	    {  
	      press[1][c] = 0;  
	      c ++;  
	      press[1][c] ++;
	    }  
	}  
 	printf("%d\n",min);  
 	return 0;  
}  



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值