題目描述:
“飛行員兄弟”這個遊戲,需要玩家順利的打開一個擁有16個把手的冰箱。
已知每個把手可以處於以下兩種狀態之一:打開或關閉。
只有當所有把手都打開時,冰箱纔會打開。
把手可以表示爲一個4х4的矩陣,您可以改變任何一個位置[i,j]上把手的狀態。
但是,這也會使得第i行和第j列上的所有把手的狀態也隨着改變。
請你求出打開冰箱所需的切換把手的次數最小值是多少。
輸入格式:
入一共包含四行,每行包含四個把手的初始狀態。
符號“+”表示把手處於閉合狀態,而符號“-”表示把手處於打開狀態。
至少一個手柄的初始狀態是關閉的。
輸出格式:
第一行輸出一個整數N,表示所需的最小切換把手次數。
接下來N行描述切換順序,每行輸入兩個整數,代表被切換狀態的把手的行號和列號,數字之間用空格隔開。
**注意:**如果存在多種打開冰箱的方式,則按照優先級整體從上到下,同行從左到右打開。
數據範圍:
1≤i,j≤4
輸入樣例:
-+--
----
----
-+--
輸出樣例:
6
1 1
1 3
1 4
4 1
4 3
4 4
AC代碼:
/*
解題思路:
因爲是4X4的,也就是2的16次方個可能,是65536,數字不算大,可以直接暴力破解
枚舉這16個開關的每一個變化的可能性,如果符合,則記錄,最後比較出最小的一個輸出即可
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <limits.h>
using namespace std;
int map[4][4];//1-打開,0+關閉
int tmpMap[4][4];//複製數組
int minCount = INT_MAX;//先讓其爲最大
vector<int> rx,ry;//最終結果的變化x,y座標
void turn(int i, int j)
{
//變化行
tmpMap[i][0] ^= 1;
tmpMap[i][1] ^= 1;
tmpMap[i][2] ^= 1;
tmpMap[i][3] ^= 1;
//變化列
tmpMap[0][j] ^= 1;
tmpMap[1][j] ^= 1;
tmpMap[2][j] ^= 1;
tmpMap[3][j] ^= 1;
//i,j變化多了一次,再次變化一次
tmpMap[i][j] ^= 1;
}
int main()
{
//input
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
char tmp;
scanf("%c",&tmp);
if(tmp == '-') map[i][j] = 1;
else map[i][j] = 0;
}
getchar();
}
//枚舉每一個開關是否變化
//用2進製表示即可,可以爲65526,再利用i>>j&1取出每一個二進制數是0或者1
for(int i = 0; i < 65536; i++)
{
memcpy(tmpMap, map, sizeof(int)*16);
vector<int> tx, ty;
int count = 0;
for(int j = 0; j < 16; j++)
{
if(i >> j & 1)//取出那個位置上的數字
{
count++;
tx.push_back(j/4);
ty.push_back(j%4);
turn(j/4,j%4);
}
}
//判斷是否符合要求
bool flag = false;
for(int r = 0; r < 4; r++)
{
for(int h = 0; h < 4; h++)
{
if(tmpMap[r][h] == 0) flag = true;
}
}
//符合要求,交換
if(!flag)
{
if(count < minCount)
{
minCount = count;
swap(tx,rx);
swap(ty,ry);
}
}
}
//輸出結果
cout << minCount << endl;
for(int i = 0; i < rx.size(); i++)
{
cout << rx[i]+1 << " "<< ry[i]+1 <<endl;
}
return 0;
}