首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

求教这里的dfs算法该如何理解

2013-08-01 
求教这里的dfs算法该怎么理解?poj2965:The Pilots Brothers refrigeratorTime Limit: 1000MSMemory Limit

求教这里的dfs算法该怎么理解?
poj2965:The Pilots Brothers' refrigerator
Time Limit: 1000MS
Memory Limit: 65536K
Total Submissions: 10158
Accepted: 3707
Special Judge
 
Description
The game “The Pilots Brothers: following the stripy elephant” has a quest where a player needs to open a refrigerator.
There are 16 handles on the refrigerator door. Every handle can be in one of two states: open or closed. The refrigerator is open only when all handles are open. The handles are represented as a matrix 4х4. You can change the state of a handle in any location [i, j] (1 ≤ i, j ≤ 4). However, this also changes states of all handles in row i and all handles in column j.
The task is to determine the minimum number of handle switching necessary to open the refrigerator.
Input
The input contains four lines. Each of the four lines contains four characters describing the initial state of appropriate handles. A symbol “+” means that the handle is in closed state, whereas the symbol “?” means “open”. At least one of the handles is initially closed.
Output
The first line of the input contains N – the minimum number of switching. The rest N lines describe switching sequence. Each of the lines contains a row number and a column number of the matrix separated by one or more spaces. If there are several solutions, you may give any one of them.
Sample Input
-+--
----
----
-+--
Sample Output
6
1 1
1 3
1 4
4 1
4 3
4 4
Source
Northeastern Europe 2004, Western Subregion

题目大意:一个冰箱有16个开关,呈方形分布(4*4矩阵),“+”表示关闭,“-”表示开着,当所有的开关为“+”时冰箱才能打开。当去翻转一个开关时,在该开关所在列和行的所有开关都要翻转,即开变关,关变开。问至少需要多少次才能打开冰箱。

网上看到的一种用DFS方法的代码:

#include<iostream>
using namespace std;

bool board[16];


int is[16];
int js[16];
bool check(){
for(int i=0;i<16;i++){
if(board[i]!=1)
return false;
}
return true;
}
void init(){
char a;
for(int i=0;i<16;i++){
cin>>a;
if(a=='+'){
board[i]=0;
}else{
board[i]=1;
}
}

}
void flip(int pos){
int i=pos/4;
int j=pos%4;
board[pos]=!board[pos];
for(int m=0;m<4;m++){
board[i*4+m]=!board[i*4+m];
board[(m)*4+j]=!board[(m)*4+j];
}
}
bool dfs(int pos,int step){
if(check()){
cout<<step<<endl;
for(int i=0;i<step;i++){
cout<<is[i]<<" "<<js[i]<<endl;
}
return true;
}
if(pos>=16){
return false;
}
if(dfs(pos+1,step))//这里是什么意思?为什么这里递归step不要加1
return true;
flip(pos);
is[step]=pos/4+1;//这里记录下了什么?
js[step]=pos%4+1;
if(dfs(pos+1,step+1))
return true;
flip(pos);
return false;

}
int main(){
init();
dfs(0,0);
}



小白看了很长时间不懂,我想请教一下这里dfs函数是什么意思?不能理解是如何搜索的。
一般DFS接受一个图的节点(状态),然后搜索完一个分支回溯再搜索另一个分支,直到搜索完整个图。
对于这个题目来说节点是什么?分支又是什么呢?而且每个节点是通过什么方式表示是否被访问过了呢? 算法 DFS 搜索
[解决办法]
节点是所有16个点。分支是该点是否做操作。这个图是个DAG所以不需要记录访问情况

>//这里是什么意思?为什么这里递归step不要加1
第一个分支情况是该点不进行操作,因此step不加1

>//这里记录下了什么?
本次操作的节点行列。因为最后需要输出。

热点排行