POJ 2965 The Pilots Brothers' refrigerator(技巧)

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

问题描述

The Pilots Brothers' refrigerator

Time Limit: 1000MS

 

Memory Limit: 65536K

Total Submissions: 29748

 

Accepted: 11535

 

Special Judge

Description

The game “The Pilots Brothers: following the stripy elephant” has a quest where a player needs to open a refrigerator.

There are 16 handles on the refrigerator door. Every handle can be in one of two states: open or closed. The refrigerator is open only when all handles are open. The handles are represented as a matrix 4х4. You can change the state of a handle in any location [i, j] (1 ≤ i, j ≤ 4). However, this also changes states of all handles in row i and all handles in column j.

The task is to determine the minimum number of handle switching necessary to open the refrigerator.

Input

The input contains four lines. Each of the four lines contains four characters describing the initial state of appropriate handles. A symbol “+” means that the handle is in closed state, whereas the symbol “−” means “open”. At least one of the handles is initially closed.

Output

The first line of the input contains N – the minimum number of switching. The rest N lines describe switching sequence. Each of the lines contains a row number and a column number of the matrix separated by one or more spaces. If there are several solutions, you may give any one of them.

Sample Input

-+--
----
----
-+--

Sample Output

6
1 1
1 3
1 4
4 1
4 3
4 4

Source

Northeastern Europe 2004, Western Subregion

------------------------------------------------------------

题意

4×4的手柄矩阵,有“开”和“关”两种状态。每次翻转一个手柄,该手柄同行同列的手柄都会翻转。求将给定手柄矩阵翻转成全开状态的最小翻转次数。

------------------------------------------------------------

思路

普通思路就是把手柄矩阵视作状态空间,求状态空间中的最短路。用广搜可以求解。

但此题有特殊解法。注意到,手柄被翻转奇数次相当于只翻转一次,翻转偶数次相当于不翻转。欲只翻转手柄(i,j),可以翻转第i行和第j列的所有手柄,共7个,这样手柄(i,j)被翻转7次,第i行和第j列的其他手柄被翻转4次,剩下的手柄被翻转2次。

因此用mat表示一个手柄被翻的次数,读入手柄矩阵时,如果手柄(i,j)是关着的,则第i行和第j列的所有mat[ii][jj]++.最后mat中值为奇数的元素就是需要翻转的手柄(顺序任意)。

------------------------------------------------------------

代码

#include<cstdio>
#include<cstring>

int main()
{
#ifndef ONLINE_JUDGE
	freopen("2965.txt", "r", stdin);
#endif
	int mat[4][4] = {};
	char str[5];
	char ch;
	int i, j, k;
	for (i=0; i<4; i++)
	{
		scanf("%s", str);
		for (j=0; j<4; j++)
		{
			ch = str[j];
			if (ch == '+')			// 有关着的把手,就把所在行所在列的把手都翻一遍,相当于只翻了这个把手
			{
				mat[i][j]++;
				for (k=0; k<4; k++)
				{
					if (k!=i)
					{
						mat[k][j]++;
					}
					if (k!=j)
					{
						mat[i][k]++;
					}
				}
			}
		}
	}
	int cnt = 0;						// 需要翻转的次数
	for (i=0; i<4; i++)
	{
		for (j=0; j<4; j++)
		{
			if (mat[i][j]%2==1)			// 奇数次翻转相当于1次翻转,偶数次翻转相当于不翻转,因此只统计奇数
			{
				cnt++;
			}
		}
	}
	printf("%d\n", cnt);
	for (i=0; i<4; i++)
	{
		for (j=0; j<4; j++)
		{
			if (mat[i][j]%2==1)
			{
				printf("%d %d\n", i+1, j+1);
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/82495936