题目大意:
翻转游戏//看到那个图片首次猜想是不是点一个方格就可以把它的颜色改编为对立的颜色???
翻转游戏是在一个4*4的矩形中放置两个碎片在16个格子中,每一块的一侧是白色的,另一侧是黑色的(都有两侧)所以每一块都是白色或者黑色在上面(朝上),
每一个回合可以翻3~5块,因此可以改变他们的颜色,白色变成黑色反之黑色变成白色。每一轮选中的都应该遵守下面的规则。
1——选择的每一块都在这16块中
2——如果选择一块,那么它邻近的上下左右都要反转(如果有的话)
这个游戏的目标是将所有的棋子都变为白色或者黑色。你需要编写一个程序计算达到目标所需要的最小翻转次数。
//题目应该是看明白了,不过没有什么思路,这个题目的类型是枚举,不过什么是枚举?不就是把所有情况都考虑出来,有想法了,准备试一下把所有的情况都写出来
//4*4就16个方格,不过因为就黑白两色,所以总共就2^16种,65536种,完全可以枚举出来,好吧,先试着下一下吧
#include<stdio.h>
#include<
string.h>
#include<queue>
#include<iostream>
using
namespace std;
#define maxn 65536
int visit[maxn+
10];
/*
* * * *
* * * *
* * * *
* * * *
*/
int dir[
4][
2] = {
0,
1,
1,
0,-
1,
0,
0,-
1};
void changeNum(
int n,
int a[][
10]);
//
把数字n转换成棋盘下标是从1到4的
int changeStr(
int a[][
10]);
//
把棋盘转换成数字
void changeXY(
int a[][
10],
int x,
int y);
//
把xy坐标的字母改变一下
int OK(
int x,
int y);
//
判断xy坐标是否合法
void BFS();
//
用宽搜从0和65536为起点搜索
int main ()
{
char ch;
int i, j, n, a[
10][
10];
BFS();
for(i=
1; i<=
4; i++)
for(j=
1; j<=
4; j++)
{
cin >> ch;
if(ch ==
'
b
')
a[i][j] =
0;
else
a[i][j] =
1;
}
n = changeStr(a);
if(visit[n])
printf(
"
%d\n
", visit[n]-
1);
else
printf(
"
Impossible\n
");
return
0;
}
void changeNum(
int n,
int a[][
10])
//
把数字n转换成棋盘下标是从1到4的
{
int i, j;
for(i=
4; i>
0; i--)
for(j=
4; j>
0; j--)
{
a[i][j] = n %
2;
n /=
2;
}
}
int changeStr(
int a[][
10])
//
把棋盘转换成数字
{
int i, j, n=
0;
for(i=
1; i<=
4; i++)
for(j=
1; j<=
4; j++)
{
n = n*
2 + a[i][j];
}
return n;
}
void changeXY(
int a[][
10],
int x,
int y)
//
把xy坐标的字母改变一下
{
int i, nx, ny;
a[x][y] =
1 - a[x][y];
for(i=
0; i<
4; i++)
{
nx = dir[i][
0] + x;
ny = dir[i][
1] + y;
if(nx, ny)
a[nx][ny] =
1 - a[nx][ny];
}
}
int OK(
int x,
int y)
//
判断xy坐标是否合法
{
if(x>
0 && x<
5 && y>
0 && y<
5)
return
1;
return
0;
}
void BFS()
//
用宽搜从0和65536为起点搜索
{
queue<
int> Q;
visit[
0] = visit[
65536] =
1;
Q.push(
0), Q.push(
65536);
while(Q.size())
{
int top = Q.front();Q.pop();
int a[
10][
10];
changeNum(top, a);
for(
int i=
1; i<=
4; i++)
for(
int j=
1; j<=
4; j++)
{
changeXY(a, i, j);
int m = changeStr(a);
if(visit[m] ==
0)
{
Q.push(m);
visit[m] = visit[top] +
1;
}
changeXY(a, i, j);
}
}
}
//
第一次尝试提交无情的WA了,不太明白为什么,找一下Bug吧
//
发现错误最大值应该是2^16-1不过提交后继续错误
#include<stdio.h>
#include<
string.h>
#include<queue>
#include<iostream>
using
namespace std;
#define maxn 65535
int visit[maxn+
10];
/*
* * * *
* * * *
* * * *
* * * *
*/
int dir[
4][
2] = {
0,
1,
1,
0,-
1,
0,
0,-
1};
void changeNum(
int n,
int a[][
10]);
//
把数字n转换成棋盘下标是从1到4的
int changeStr(
int a[][
10]);
//
把棋盘转换成数字
void changeXY(
int a[][
10],
int x,
int y);
//
把xy坐标的字母改变一下
int OK(
int x,
int y);
//
判断xy坐标是否合法
void BFS();
//
用宽搜从0和65536为起点搜索
int main ()
{
char ch;
int i, j, n, a[
10][
10];
BFS();
for(i=
1; i<=
4; i++)
for(j=
1; j<=
4; j++)
{
cin >> ch;
if(ch ==
'
b
')
a[i][j] =
0;
else
a[i][j] =
1;
}
n = changeStr(a);
if(visit[n])
printf(
"
%d\n
", visit[n]-
1);
else
printf(
"
Impossible\n
");
return
0;
}
void changeNum(
int n,
int a[][
10])
//
把数字n转换成棋盘下标是从1到4的
{
int i, j;
for(i=
4; i>
0; i--)
for(j=
4; j>
0; j--)
{
a[i][j] = n %
2;
n /=
2;
}
}
int changeStr(
int a[][
10])
//
把棋盘转换成数字
{
int i, j, n=
0;
for(i=
1; i<=
4; i++)
for(j=
1; j<=
4; j++)
{
n = n*
2 + a[i][j];
}
return n;
}
void changeXY(
int a[][
10],
int x,
int y)
//
把xy坐标的字母改变一下
{
int i, nx, ny;
a[x][y] =
1 - a[x][y];
for(i=
0; i<
4; i++)
{
nx = dir[i][
0] + x;
ny = dir[i][
1] + y;
if(nx, ny)
a[nx][ny] =
1 - a[nx][ny];
}
}
int OK(
int x,
int y)
//
判断xy坐标是否合法
{
if(x>
0 && x<
5 && y>
0 && y<
5)
return
1;
return
0;
}
void BFS()
//
用宽搜从0和65536为起点搜索
{
queue<
int> Q;
visit[
0] = visit[
65536] =
1;
Q.push(
0), Q.push(maxn);
while(Q.size())
{
int top = Q.front();Q.pop();
int a[
10][
10];
changeNum(top, a);
for(
int i=
1; i<=
4; i++)
for(
int j=
1; j<=
4; j++)
{
changeXY(a, i, j);
int m = changeStr(a);
if(visit[m] ==
0)
{
Q.push(m);
visit[m] = visit[top] +
1;
}
changeXY(a, i, j);
}
}
}
//
继续找BUG
找到BUG初始化不完善
//
应该仔细 成功AC
////////////////////////////////////
// visit[0] = visit[65536] = 1;这里,应该是65535