菜鸟的ACM之路(1)北大MOOC算法基础笔记__第一周__枚举

第一周 枚举

1.完美立方(循环条件优化)

2.生理周期(循环跳步优化)

3.POJ1013称硬币

4.POJ1222熄灯问题(局部分析)(利用二进制枚举)


例题四也就是熄灯问题值得反复学习一下,下面附上本人的AC代码= =,其实和老师的差不多,打一遍看看哪部分没有理解,也耗费了很多时间,位运算脑子有点转不过来

#include
#include
#include
using namespace std;
//防止越界就不设5了 
int map[6];  //输入 
int ing[6];  //正在处理 
int ans[6];  //输出 

int getnum(int num, int n) // num == 输入的数字, n == 要取的位数 
{
	return (num >> n) & 1;
}

void change(int &num, int n)
{
	num ^= (1 << n);
	return;	
} 

void setnum(int &num, int n, int in) // in == 要设置的数字
{
	if(in)
		num |= (1 << n);
	else
		num &= ~(1 << n);
	return;
} 

void outans(int n)
{
	cout << "PUZZLE #" << n << endl;
	for(int i = 0; i < 5; i++)
		for(int j = 0; j < 6; j++)
		{
			cout << getnum(ans[i], j);
			if(j == 5)
				cout << endl;
			else
				cout << " ";
		}
	return;
}

int main()
{
	int n, temp;
	cin >> n;
	for(int puzzle = 1; puzzle <= n; puzzle++)
	{
		int i, j, k;
		//读入数据 
		for(i = 0; i < 5; i++)
			for(j = 0; j < 6; j++)
			{
				cin >> temp;
				setnum(map[i], j, temp);
			}
		
		for(i = 0; i < 64; i++)
		{
			int swit = i;
			memcpy(ing, map, sizeof(map));
			
			for(j = 0; j < 5; j++)
			{
				ans[j] = swit;
				for(k = 0; k < 6; k++)
				{
					if(getnum(swit, k))          // 改变本行的数据 
					{
						if(k > 0)
							change(ing[j], k - 1);
						if(k < 5)
							change(ing[j], k + 1);
						change(ing[j], k);
					}
				}
				if(j < 4)						//改变下一行的数据 
					ing[j + 1] ^= swit;
				swit = ing[j];
			}
				if(ing[4] == 0)               
				{
					outans(puzzle);
					break;
				}
		}
	}
		
	return 0; 
}

你可能感兴趣的:(菜鸟初识算法)