难度:普及/提高-
题目类型:搜索/枚举/模拟
提交次数:3
涉及知识:DFS
题目背景
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即可。
代码:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int a[5][5]; 5 bool visited[5][5]; 6 int ans = 1000; 7 void print(){ 8 int i, j; 9 for(i = 1; i < 4; i++){ 10 for(j = 1; j < 4; j++) 11 cout<<a[i][j]<<" "; 12 cout<<endl; 13 } 14 }//打印,用于调试 15 bool finished(){ 16 bool ans = true; 17 int i, j; 18 for(i = 1; i <= 3; i++) 19 for(j = 1; j <= 3; j++) 20 if(!a[i][j]) return false; 21 return true; 22 }//判断是否全亮 23 void click(int x, int y){ 24 a[x][y] = !a[x][y]; 25 a[x-1][y] = !a[x-1][y]; 26 a[x+1][y] = !a[x+1][y]; 27 a[x][y+1] = !a[x][y+1]; 28 a[x][y-1] = !a[x][y-1]; 29 }//点击函数 30 void dfs(int step){ 31 int i, j; 32 if(finished()){ 33 if(ans>step) ans = step; 34 return; 35 } 36 if(step>=9) return; //减枝 37 if(step>ans) return; 38 else{ 39 for(i = 1; i <= 3; i++) 40 for(j = 1; j <= 3; j++) 41 if(!visited[i][j]){ 42 click(i, j); 43 visited[i][j] = true; 44 //cout<<step<<endl; 45 //print(); 46 dfs(step+1);//注意++step会出错 47 click(i, j); //取消=按回去 48 visited[i][j] = false; 49 } 50 } 51 } 52 int main(){ 53 int i, j; 54 for(i = 1; i <= 3; i++) 55 for(j = 1; j <= 3; j++) 56 cin>>a[i][j]; 57 dfs(0);//不是1 58 cout<<ans; 59 return 0; 60 }
备注:
这道题耗了我一天的时间!还要选课什么的,真是焦头烂额。一会儿我还要去做化学和物理……
问题挺多的。思路就是搜索。然而DFS从来没写对过,仿佛受了诅咒。老师说我思路乱,我发现其实是因为没有严格按DFS框架来。有一个问题,最优解里一个灯不可能按2次,我最开始居然没想明白!另外应该是dfs(0),想想就知道了。
应该是dfs(step+1)不要写++step!会出错!出错!出错!
被老师强迫着思考为什么++step会出错。
想明白了:
dfs(++step);拆成两行就是step = step+1; dfs(step); 这样等dfs一圈回来,step已经不是原来的那个step了,物是人非。