算法题:一个圆环上有100个灯泡,灯泡有打开和关闭两种状态,灯泡的状态随机,按一个灯泡的开关,相邻的两个灯泡的状态也发生一次变化。比如暗-亮-暗,按中间灯泡,变化为亮-暗-亮。问设计一道算法,使得所有

9 篇文章 0 订阅
7 篇文章 1 订阅

代码如下:
每次输入100个随机的0和1,然后按照下面三个步骤就可以:
第一阶段,如果给100个灯泡编号0~99 ,顺序往下走,如果灯是亮的就不管,灭的就按下后面灯泡使这个灯亮(在第一循环内,也就是还没有从99走到0)。如果都是亮的那正好万事大吉完事!如果不是的话,期间肯定有是灭的,不管它在哪个位置,重复【亮的就不管,灯是灭的把下一个灯泡按一下开关】规则(都在第一轮循环里面)。98号灯假定是灭的,看99号灯是灭还是亮,如果99号灯是灭的,那就再按一下99号灯的开关,这样全环只有一个灭的灯(0号灯)。

如果99号灯是亮的,这样只有98号灯是灭的。总之,全环只有一个灯是灭的。

第二阶段,将那个灭的灯标记为0号灯,后面的灯依次按顺序排序,每3个一组,中间的那个灯按开关,举例,将2号灯开关打开,1,2,3号灯就都灭了,整个循环跑完,所有的灯都灭了。

第三阶段,每个灯泡的开关都按一遍。以上步骤就可以使最后的灯泡全亮。
原文链接

#include <iostream>
#include <vector>
#include <ctime>
using namespace std;


void Print(const vector<int> & vec)
{
	for (auto v : vec)
	{
		cout << v << " ";
	}
	cout << endl;
}

int start = 0;
int n = 100;
int unit = 3;

void f(vector<int> & vec, int idx) // 按下
{

	if (idx > int(vec.size())) return;
	int cur_idx = idx > n - 1 ? start : idx;
	int left_idx = cur_idx - 1 >= start ? cur_idx - 1 : n - 1;
	int right_idx = cur_idx + 1 < n ? cur_idx + 1 : start;
	vec[cur_idx] = abs(1 - vec[cur_idx]);
	vec[left_idx] = abs(1 - vec[left_idx]);
	vec[right_idx] = abs(1 - vec[right_idx]);

}


int main()
{
	srand((unsigned)time(NULL));
	vector<int> vec;

	vec.resize(n);
	for (int i = 0; i < n; i++)
	{
		int r = rand() % 2;
		vec[i] = r;
	}
	cout << " ori vec" << endl;

	//first
	cout << " first " << endl;
	for (int i = 0; i < n - 1; i++)
	{
		if (!vec[i])
		{
			f(vec, i+1);

		}
	}
	//Print(vec);

	int flag = 0;
	for (int j = start; j < n; j++)
	{
		if (!vec[j])
		{
			flag = j;
			break;
		}
	}
	if (!flag)
	{
		cout << "all is ok in first step" << endl;
		return 0;
	}

	//second

	int s = flag;
	int cur_idx = s + 1 < n ? s + 1 : s + 1 - n + 1;
	
	for (int i = 0; i < n - 1; i+= unit)
	{
		f(vec, cur_idx);
		cur_idx += unit;
	}

	for (int i = 0; i < n ; i++)
	{
		f(vec, i);
	}

	Print(vec);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值