题目背景
pmshz在玩一个益(ruo)智(zhi)的小游戏,目的是打开九盏灯所有的灯,这样的游戏难倒了pmshz。。。
题目描述
这个灯很奇(fan)怪(ren),点一下就会将这个灯和其周围四盏灯的开关状态全部改变。现在你的任务就是就是告诉pmshz要全部打开这些灯。
例如
0 1 1
1 0 0
1 0 1
点一下最中间的灯【2,2】就变成了
0 0 1
0 1 1
1 1 1
再点一下左上角的灯【1,1】就变成了
1 1 1
1 1 1
1 1 1
达成目标。最少需要2步。
输出2即可。
输入格式
九个数字,3*3的格式输入,每两个数字中间只有一个空格,表示灯初始的开关状态。(0表示关,1表示开)
输出格式
1个整数,表示最少打开所有灯所需要的步数。
输入输出样例
输入
0 1 1
1 0 0
1 0 1
输出
2
代码如下:
#include <iostream>
using namespace std;
const int N = 5;
int g[N][N];
int ans = 10;
void turn(int x,int y)//开关灯
{g[x][y] = 1-g[x][y];g[x-1][y] = 1-g[x-1][y];g[x+1][y] = 1-g[x+1][y];g[x][y+1] = 1-g[x][y+1];g[x][y-1] = 1-g[x][y-1];
}void dfs(int n)
{if (n > ans) return ;//剪枝,不剪枝会超时//超过最小的次数就返回,初始次数为10,规律:它总共步骤不会超过9次int sum = 0;for (int i = 1;i<=3;i++)for (int j = 1;j<=3;j++)sum+=g[i][j];if (sum==9) ans = min(ans,n-1);//加起来等于9,就是灯全部亮的情况for (int i = 1;i<=3;i++)for (int j = 1;j<=3;j++){turn(i,j);dfs(n+1);turn(i,j);}
}int main()
{for (int i = 1;i<=3;i++)for (int j = 1;j<=3;j++)cin>>g[i][j];dfs(1);cout<<ans<<endl;return 0;
}
增加一个标记数组,剪枝。
代码如下:
#include <iostream>
using namespace std;
const int N = 5;
int g[N][N];
int ans = 10;
bool vis[N][N];void turn(int x, int y) { //开关灯g[x][y] = 1 - g[x][y];g[x - 1][y] = 1 - g[x - 1][y];g[x + 1][y] = 1 - g[x + 1][y];g[x][y + 1] = 1 - g[x][y + 1];g[x][y - 1] = 1 - g[x][y - 1];
}void dfs(int n) {if (n > ans)return ;//剪枝,不剪枝会超时//超过最小的次数就返回,初始次数为10,规律:它总共步骤不会超过9次int sum = 0;for (int i = 1; i <= 3; i++)for (int j = 1; j <= 3; j++)sum += g[i][j];if (sum == 9)ans = min(ans, n - 1); //加起来等于9,就是灯全部亮的情况for (int i = 1; i <= 3; i++)for (int j = 1; j <= 3; j++) {if (!vis[i][j]) {vis[i][j] = true;turn(i, j);dfs(n + 1);vis[i][j] = false;turn(i, j);}}
}int main() {for (int i = 1; i <= 3; i++)for (int j = 1; j <= 3; j++)cin >> g[i][j];dfs(1);cout << ans << endl;return 0;
}