一个房间中有 n 盏灯最初是开着的,并且墙上有 4 个开关。在对开关进行 m 次未知的操作后,你需要返回这 n 盏灯有多少种不同的状态。
假设 n 盏灯的标号为 [1, 2, 3 …, n], 4 个开关的功能如下:
- 将所有灯从开变成关,从关变成开。
- 将标号为偶数的灯从开变成关,从关变成开。
- 将标号为奇数的灯从开变成关,从关变成开。
- 将标号为 (3k + 1) 的灯从开变成关,从关变成开,k = 0, 1, 2…
样例:
给出 n = 1, m = 1。
返回 2 // 状态可以是: [on], [off]
给出 n = 2, m = 1。
返回3 // 状态可以是: [on, off], [off, on], [off, off]
思路:
当m>=3时,
由于button1+button2等效于button3,
button1+button3等效于button2
button2+button3等效于button1
对于1,2,3,4四个按钮,仅有其中之一,共5种情况;
11,2222和原灯泡状态一样,1,111所表示的状态是一样的。
有上述所知1,3->2,1,2->3,2,3->1状态与单个1,2,3相同,
只剩下1,4,2,4,3,4,3种情况。
故返回8。
剩下的可以把按钮设置成函数,一一求出。
#ifndef C704_H
#define C704_H
#include<iostream>
#include<string>
#include<set>
#include<cmath>
using namespace std;
class Solution {
public:
/*
* @param : number of lights
* @param : number of operations
* @return: the number of status
*/
int flipLights(int n, int m) {
// write your code here
if (n <= 0)
return 0;
if (m <= 0)
return 1;
if (n>=3&&m >= 3)
return 8;
set<string> set;
for (int i = 0; i <= m; ++i)
{
for (int j = 0; j <= m; ++j)
{
for (int k = 0; k <= m; ++k)
{
if (m - i - j - k >= 0)
{
string str(n, '1');
int num1 = i, num2 = j, num3 = k, num4 = m - i - j - k;
while (num1 > 0)
{
button1(str);
num1--;
}
while (num2 > 0)
{
button2(str);
num2--;
}
while (num3 > 0)
{
button3(str);
num3--;
}
while (num4 > 0)
{
button4(str);
num4--;
}
set.insert(str);
}
}
}
}
return set.size();
}
void button1(string &s)
{
for (auto &c : s)
{
if (c == '0')
c = '1';
else
c = '0';
}
}
void button2(string &s)
{
for (int i = 0; i < s.size(); ++i)
{
if ((i + 1) % 2 == 0)
{
if (s[i] == '0')
s[i] = '1';
else
s[i] = '0';
}
}
}
void button3(string &s)
{
for (int i = 0; i < s.size(); ++i)
{
if ((i + 1) % 2 != 0)
{
if (s[i] == '0')
s[i] = '1';
else
s[i] = '0';
}
}
}
void button4(string &s)
{
for (int i = 0; i < s.size(); ++i)
{
if ((i + 1) % 3 == 1)
{
if (s[i] == '0')
s[i] = '1';
else
s[i] = '0';
}
}
}
};
#endif