POJ 2965 DFS解法 原理与1753类似 稍加改造即可ac

来源:互联网 发布:尘埃拉力赛 知乎 编辑:程序博客网 时间:2024/06/10 01:39


//在poj1753 基础上改造一下,  ac用时大概 300~500 ms   不会超时

//思路非常简单,先dfs求出最小次数,再次dfs记录下 达到最小次数的 路径即可

#include<iostream>

using namespace std;
#include<cstdio> 
#include<cstring>


bool arr[4][4]={false}; // + closed用0表示关  - open用1表示开 
int ans = 999999;    //其实只要初始化为17 就行,最多转16次 , 
bool flag;
int a[20],b[20]; // 两个数组用来记录下标,当然你也可以有struct pos{ int x,int y} array[20]; 


void flip(int x,int y)
{
int i,j;
for(i=0;i<4;i++)
{
arr[i][y] = !arr[i][y]; // 翻所在列 
}
for(j=0;j<4;j++)
{
if(j!=y)
{
arr[x][j] = !arr[x][j]; // 翻所在行 
}
}
}


bool judge() //判断是否全开,即全部为 -  即是否为true 
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(arr[i][j] != true)
return false;
return true;
}


void dfs(int x,int y,int deep){  //dfs深度搜索 
if(judge()){
if(deep < ans)
ans = deep;   //ans 保存最小翻转次 
return ;
}
if(x<0 || x>3 || y<0 || y>3)
return ;
int nx,ny;
nx=(x+1)%4;    
ny=y+(x+1)/4;
flip(x,y);
dfs(nx,ny,deep+1);
flip(x,y);
dfs(nx,ny,deep);
}


void Dfs(int x,int y,int deep){  //dfs深度搜索 
if(judge()){
if(deep == ans)
flag=true;   //已达到最小翻转次数 
return ;
}
if(flag || x<0 || x>3 || y<0 || y>3)  //多了一个条件满足flag即可退出 
return ;
int nx,ny;
nx=(x+1)%4;   // 注意此处按列搜索,也可稍加改造按列搜索   结果可能与答案不一样,只要找出一条翻转路径即可 
ny=y+(x+1)/4;
/*
y = (y+1)%4;   //相当于按行遍历  这种写法 测试样例与答案一样 
    nx = x + (y+1)/4;
*/
flip(x,y);
Dfs(nx,ny,deep+1);
a[deep]=x; //记录下标x   
b[deep]=y; //记录下标y 
flip(x,y);
Dfs(nx,ny,deep);
}


int main(){
char str[5];
int i,j;
for(i=0;i<4;i++)
{
cin >> str;
for(j=0;j<4;j++)
if(str[j] == '-')
arr[i][j] = true;
}
dfs(0,0,0); // 先计算出 最小翻转次数 
flag=false;
Dfs(0,0,0); //再次Dfs 稍作修该 保存路径 , 当 达到 dfs求出最小次数ans 即可将flag 表为true 
  cout << ans << endl;
  for(i=0;i<ans;i++){
  cout << a[i]+1 <<" " << b[i]+1 << endl;  
//注意 he state of a handle in any location [i, j] (1 ≤ i, j ≤ 4)
//行列都是从1开始  ,我开的数组是 从(0,0) ~ (3,3) 
}
return 0;
}
0 0
原创粉丝点击