电灯切换-LintCode

204 篇文章 0 订阅

一个房间中有 n 盏灯最初是开着的,并且墙上有 4 个开关。在对开关进行 m 次未知的操作后,你需要返回这 n 盏灯有多少种不同的状态。
假设 n 盏灯的标号为 [1, 2, 3 …, n], 4 个开关的功能如下:

  1. 将所有灯从开变成关,从关变成开。
  2. 将标号为偶数的灯从开变成关,从关变成开。
  3. 将标号为奇数的灯从开变成关,从关变成开。
  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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值