POJ 2965 DFS解法 原理与1753类似 稍加改造即可ac
2017-05-01 18:02
351 查看
//在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;
}
//思路非常简单,先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;
}
相关文章推荐
- poj 1753||poj 2965 枚举+dfs
- POJ 1753 Flip Game(类似与N皇后问题的DFS)
- POJ——2965(枚举,类似1753)
- POJ2965 状态压缩+BFS,DFS枚举,以及大牛的解法~
- poj 1753 2965
- poj2965(枚举||dfs)
- POJ 2965 The Pilots Brothers' refrigerator(枚举+DFS)
- POJ 1753 Flip Game(DFS)
- POJ-1753(DFS,Notation,Bit operation,Queue)
- poj 1129 DFS 无剪枝就可AC
- POJ 1753 POJ 2965 解题报告
- poj 1014 dividing(本解法可ac 但错误!!!)
- 【dfs】poj1753——Flip Game
- POJ 1753 ID+DFS
- poj 2965 The Pilots Brothers' refrigerator (迭代加深dfs)
- poj 2965 dfs+枚举
- poj 1753 枚举加dfs
- POJ 1753 和 2965这个对现在的我来说不是水体,不能增加自信。。
- POJ 1753 Flip Game(枚举+DFS)
- POJ2965,The Pilots Brothers' refrigerator,枚举,DFS