题目连接:点击打开链接
题目大意:
这一题大意如下:
一个冰箱上有4*4共16个开关,改变任意一个开关的状态(即开变成关,关变成开)时,此开关的同一行、同一列所有的开关都会自动改变状态。要想打开冰箱,要所有开关全部打开才行。
输入:一个4×4的矩阵,+表示关闭,-表示打开;
输出:使冰箱打开所需要执行的最少操作次数,以及所操作的开关坐标。
#include<iostream>
#include<stdio.h>
using namespace std;
bool vis[10][10] = { false }; //将棋盘初始状态全部设置为false
int ri[16], cj[16];
int step; //记录改变状态的次数
bool flag;
bool finish() //开关为全开的状态
{
for(int i=3;i<7;i++)
for (int j = 3; j < 7; j++)
{
if (vis[i][j] != true)
return false;
}
return true;
}
void filp(int row,int col) //翻棋,也就是改变开关状态
{
vis[row][col] = !vis[row][col];
for (int i = 3; i < 7; i++) //注意翻棋方法,防止超时
{ // 这里使用10x10矩形,多余操作有“三圈”翻棋
vis[i][col] = !vis[i][col];
}
for (int j = 3; j < 7; j++)
{
vis[row][j] = !vis[row][j];
}
}
void dfs(int row, int col, int deep)
{
if (deep == step) //判断是否为全为开
{
flag = finish();
return;
}
if (flag || row == 7) return; //判断是否超界
filp(row, col); //翻棋
ri[deep] = row; //记录被翻棋的横坐标
cj[deep] = col; //记录被翻棋的纵坐标
if (col < 6)
dfs(row, col+1, deep + 1);
else
dfs(row+1,3,deep+1);
filp(row, col);
if (col < 6)
dfs(row, col + 1, deep);
else
dfs(row+1,3,deep);
return ;
}
int main()
{
int i, j;
char temp;
for (i = 3; i <= 6; i++) //这里使用10x10矩形,多余操作有“三圈”翻棋!
{
for (j = 3; j <= 6; j++)
{
cin >> temp;
if (temp == '-')
vis[i][j] = true;
}
}
for (step = 0; step <= 16; step++) //考虑到4x4=16格,而每一格只有黑白两种情况,则全部的可能性为2^16
{
dfs(3, 3, 0);
if (flag)
break;
}
cout << step << endl;
for ( i = 0; i < step; i++)
{
cout << ri[i] - 2 << " " << cj[i] - 2 << endl; //因为横纵坐标是从3开始的,所以要减去2
}
}