【MOOC】【枚举】4.熄灯问题——位运算

Description
有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。

Input
第一行是一个正整数N,表示需要解决的案例数。每个案例由5行组成,每一行包括6个数字。这些数字以空格隔开,可以是0或1。0表示灯的初始状态是熄灭的,1表示灯的初始状态是点亮的。
Output
对每个案例,首先输出一行,输出字符串“PUZZLE #m”,其中m是该案例的序号。接着按照该案例的输入格式输出5行,其中的1表示需要把对应的按钮按下,0则表示不需要按对应的按钮。每个数字以一个空格隔开。
Sample Input
2
0 1 1 0 1 0
1 0 0 1 1 1
0 0 1 0 0 1
1 0 0 1 0 1
0 1 1 1 0 0
0 0 1 0 1 0
1 0 1 0 1 1
0 0 1 0 1 1
1 0 1 1 0 0
0 1 0 1 0 0
Sample Output
PUZZLE #1
1 0 1 0 0 1
1 1 0 1 0 1
0 0 1 0 1 1
1 0 0 1 0 0
0 1 0 0 0 0
PUZZLE #2
1 0 0 1 1 1
1 1 0 0 0 0
0 0 0 1 0 0
1 1 0 1 0 1
1 0 1 1 0 1

解题思路:
枚举第一行的开关情况,因为第一行要全部熄灭,所以第二行的开关可由第一行的开关情况以及第一行灯的状态推算出来。依次可以推算出第3,4,5行的开关,然后再验证第五行是否全熄灭。全熄灭则为正确答案。

/*
4. 熄灯问题 
-有一个由按钮组成的矩阵,其中每行有6个按钮,共5行 
-每个按钮的位置上有一盏灯
-当按下一个按钮后,该按钮以及周围位置(上下左右)的灯都会改变状态

知识点注意:
1.异或:相同位不同则为1,相同则为0 
2.将int 类型赋值给char 类型的结果
    char a;
    int b = 54;
    cout << "a : " << a << endl;
    cout << "b : " << b << endl;
    a = b;
    cout << "after a = b , a = " << a << endl;  
输出结果 a = 6;分析如下
-char a = 54;
-ASCII码54对应字符为'6'
-cout输出字符6 
*/ 
#include <iostream>
#include <cstring>
#include <string>
#include <memory.h>

using namespace std;
char oriLights[5];
char lights[5];
char result[5];

int GetBit(char c, int n)
{
    return (c >> n) & 1; 
}

void SetBit(char & c, int i, int v)
{
    if( v )
        c |= (1 << i);
    else 
        c &= ~(1 << i);        
}

void FlipBit(char & c, int i)
{
    c ^= (1 << i); 
}

void OutputResult(int t,char r[])
{
    cout << "PUZZLE #"<< t << endl;
    for(int i = 0; i < 5; ++i){
        for(int j = 0; j < 6; ++j){
            cout << GetBit(r[i],j);
            if(j < 5)
                cout << ' ';
        }
        cout << endl;
    }       
}

int main()
{
    int T;
    cin >> T;
    for(int t = 1; t <= T; ++t){
        for( int i = 0; i < 5; ++i ){
            for (int j = 0; j < 6; ++j){
                int s;
                cin >> s;
                SetBit(oriLights[i],j,s);
            }
        }
        for(int n = 0 ; n < 64 ; ++n){ //2的6次方等于64,枚举第一行从000000到111111的所有情况 
            int switchs = n;
            memcpy(lights,oriLights,sizeof(oriLights)); //函数原型:void *memcpy(void *dest, const void *src, size_t n);
            for(int l = 0; l < 5; ++l){
                result[l] = switchs;
                for(int m = 0; m < 6; ++m){
                    if( GetBit(switchs,m) ){
                        if( m > 0)
                            FlipBit(lights[l],m-1);
                        FlipBit(lights[l],m);
                        if( m < 5 )
                            FlipBit(lights[l],m+1);

                    }
                }
                if( l < 4 )
                    lights[l+1] ^= switchs; //异或:相同位不同则为1,相同则为0
                switchs = lights[l];
            }
            if(lights[4] == 0){
                OutputResult(t,result);
                break;
            }
        }
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Python的SciPy库中的dblquad函数来计算双重积分。以下是一个示例程序,用于计算双重积分: ```python from scipy.integrate import dblquad import numpy as np # 定义被积函数 def integrand(x, y): return np.exp(-x*y) # 定义积分区间 x_lower = 0 x_upper = 1 y_lower = lambda x: 0 y_upper = lambda x: 1-x # 计算双重积分 result, error = dblquad(integrand, x_lower, x_upper, y_lower, y_upper) # 输出结果 print("Result: ", result) print("Error: ", error) ``` 在这个例子中,我们计算了双重积分$$\int_{0}^{1}\int_{0}^{1-x} e^{-xy}dydx.$$ 我们首先定义了被积函数integrand(x, y)。然后我们定义了积分区间,其中y的积分上限和下限都是函数x的函数。最后我们使用dblquad函数来计算积分结果和误差,并将它们打印出来。 ### 回答2: 编写Python程序求解双重积分可以使用数值积分的方法,如矩形法、梯形法或辛普森法。下面以矩形法为例进行说明。 首先,我们需要将双重积分转化为二重迭代的形式。根据给出的链接中的双重积分,可以发现积分范围为x从0到1,y从0到2,因此可以将双重积分表示为两重嵌套的积分形式。 然后,我们可以使用矩形法对双重积分进行近似计算。具体步骤如下: 在程序中引用数值计算库,如numpy库。 设置步长h1和h2,用于控制矩形的划分精度。 定义双重积分函数f(x, y),根据给定的双重积分表达式编写对应的Python函数。 使用两个嵌套循环,分别迭代x和y的取值范围,每次迭代计算f(x, y)并进行累加。这里要注意,x的取值范围是[0, 1],y的取值范围是[0, 2]。 最后,输出计算得到的近似积分值。 下面是一个简化的代码示例: ```python import numpy as np def f(x, y): return x**2 + y def double_integral(): h1 = 0.001 # x轴步长 h2 = 0.001 # y轴步长 integral_value = 0.0 # 积分值 for x in np.arange(0, 1, h1): for y in np.arange(0, 2, h2): integral_value += f(x, y) * h1 * h2 return integral_value result = double_integral() print("双重积分的近似值为:", result) ``` 以上代码中,我们设置了较小的步长h1和h2来提高积分的精度,然后通过两个嵌套循环对二重积分进行近似计算。计算完成后,输出得到的近似积分值。 需要注意的是,由于双重积分结果可能是一个较大的数值,因此可能需要适当调整步长和划分区域的细度,以提高计算的准确性和效率。 ### 回答3: 要编写Python程序求解双重积分,我们可以使用数值积分的方法来逼近积分值。下面是一个简单的Python程序: ```python import numpy as np def f(x, y): return np.sin(x*y) def double_integral(a, b, c, d, n): dx = (b - a) / n dy = (d - c) / n integral = 0 for i in range(n): for j in range(n): x = a + i*dx + dx/2 y = c + j*dy + dy/2 integral += f(x, y) integral *= dx*dy return integral a = 0 # 第一个积分的下限 b = np.pi # 第一个积分的上限 c = 0 # 第二个积分的下限 d = np.pi # 第二个积分的上限 n = 100 # 将每个积分区间分成n个小区间 result = double_integral(a, b, c, d, n) print("双重积分的近似值:", result) ``` 上述程序中,`f(x, y)`是被积函数,`double_integral(a, b, c, d, n)`是求解双重积分的函数。在函数中,我们将每个积分区间分成n个小区间,然后通过循环求和的方式,依次计算每个小区间的中点的函数值,并累加得到积分值。最后,将每个小区间的宽度dx和dy乘起来,得到整个双重积分的近似值。 以上是一个简单的数值积分求解双重积分的Python程序,可以根据需要进行调整和修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值