POJ 2965 The Pilots Brothers' refrigerator 枚举

    题目:http://poj.org/problem?id=2965

    和1753很类似,也是一个4*4的棋盘,通过开关锁,来使得棋盘上所有的锁都是OPEN,当打开一个锁的时候,会同时修改行和列锁的状态。分析:

    (1)同样的,每个格子的锁只要开一次就够了,因为如果打开两次,等于没有打开。

    (2)棋盘的状态跟开锁的顺序没有关系,只跟开锁的个数和位置有关系。

    如果用0-1表示开不开一个锁,那么相当于求棋盘格子的01序列,总共有2^16种可能性,因此可以用枚举的方法。方式和1753很类似(见上一个博客),但是多加了一个path用于记录开关锁的位置。代码如下:

#include <stdio.h>

#define  ONLINE

void online()
{
#ifdef  ONLINE
#else
	freopen("2965.in", "r", stdin);
	freopen("2965.out", "w", stdout);
#endif
}

int map = 0;
const int END = 0X0000;
const int SIZE = 16;
const int state[SIZE] = {
	0xF888, 0xF444, 0xF222, 0xF111,
	0x8F88, 0x4F44, 0x2F22, 0x1F11,
	0x88F8, 0x44F4, 0x22F2, 0x11F1,
	0x888F, 0x444F, 0x222F, 0x111F
};
int result = 17;

int path=0;//用于记录路径

void read()
{
	char c;
	for (int i=0; i < SIZE; i++)
	{
		c = getchar();

		if (c == '+')
		{
			map = map << 1;
			map = map ^ 1;
		}//end if
		else if (c == '-')
		{
			map = map << 1;
		}
		else{
			i --;
		}//end else
	}//end for
}

void search(int idx, int step, int p)
{
	if (step >= result)
	{
		return;
	}
	if (idx >= SIZE)
	{
		if (map == END && step < result)
		{
			result = step;
			path = p;
		}//end if
		return;
	}

	p = p << 1;
	p = p^1;
	map = map ^ state[idx];
	search(idx+1, step +1, p);
	map = map^state[idx];
	p = p >> 1;

	p = p << 1;
	search(idx+1, step, p);
	p = p >>1;
}

void print()
{
	printf("%d\n", result);
	
	//打印步骤
	int bit = 15;
	for (int i=1; i <=4; i ++)
	{
		for (int j=1; j <= 4; j ++)
		{
			if ((path >> bit)&1 == 1)
			{
				printf("%d %d\n", i, j);
			}// end if
			bit --;
		}//end for 
	}//end for
}


int main()
{
	online();
	read();
	search(0, 0, 0);
	print();
	return 0;
}
    运行结果如下:

2965 Accepted 160K 63MS C++ 1430B 2011-07-29 22:17:01


你可能感兴趣的:(POJ 2965 The Pilots Brothers' refrigerator 枚举)