poj 2965 dfs+枚举
2013-09-03 17:21
423 查看
此题的难点在于数学规律的寻找
1、搞清楚棋盘的所有状态,由于翻转一个位置偶数次不会对该位置以及相应的行和列的状态产生影响,翻转奇数次又相当于翻转一次,因此,翻转的时候可以不考虑翻转哪个位置的先后顺序,这样所有的状态是为2的16次方。
2、由所有状态可以建立一颗而叉搜索树,没个位置有两个分叉,一个是翻转,一个是不翻转,树的最高高度为16,因为可以加快搜索的速度,在搜索的过程中,搜到所有可行解,并且记录翻转次数的最少的可行解。
#include <stdio.h>
struct move
{
int i,j;
}minseq[100],tempseq[100];
int refri[4][4];
int min;
bool isopen()
{
int i,j;
for (i=0;i<4;i++)
for (j=0;j<4;j++)
{
if (refri[i][j])
return false;
}
return true;
}
void reverse(int i,int j)
{
int x;
refri[i][j] = !refri[i][j];
for (x = 0;x<4;x++)
{
if (x!=j)
refri[i][x] = !refri[i][x];
if (x!=i)
refri[x][j] = !refri[x][j];
}
return ;
}
bool dfs(int cow,int col,int depth)
{ //当前已翻转次数
int i;
if (isopen())
{
if (depth < min)
{
min = depth;
for (i=0;i<depth;i++)
{
minseq[i].i = tempseq[i].i;
minseq[i].j = tempseq[i].j;
}
}
return true;
}
else
{
if (depth >= 16 || depth > min || cow > 3)
return false;
tempseq[depth].i = cow;
tempseq[depth].j = col;
reverse(cow,col);
if (col<3)
dfs(cow,col+1,depth+1); ///翻转该位后的操作
else
dfs(cow+1,0,depth+1);
reverse(cow,col);
if (col<3)
dfs(cow,col+1,depth); ///不翻转该位后的操作
else
dfs(cow+1,0,depth);
}
return false;
}
int main()
{
char temp;
int i,j;
for (i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
scanf("%c",&temp);
if (temp == '-')
refri[i][j] = 0;
else
refri[i][j] = 1;
}
getchar();
}
min = 1000000;
dfs(0,0,0);
printf("%d\n",min);
for (i=0;i<min;i++)
{
printf("%d %d\n",minseq[i].i+1,minseq[i].j+1);
}
return 0;
}
一开始做这道题,没有考虑翻转的特殊性,只是很笨的用dfs进行搜索。
1、搞清楚棋盘的所有状态,由于翻转一个位置偶数次不会对该位置以及相应的行和列的状态产生影响,翻转奇数次又相当于翻转一次,因此,翻转的时候可以不考虑翻转哪个位置的先后顺序,这样所有的状态是为2的16次方。
2、由所有状态可以建立一颗而叉搜索树,没个位置有两个分叉,一个是翻转,一个是不翻转,树的最高高度为16,因为可以加快搜索的速度,在搜索的过程中,搜到所有可行解,并且记录翻转次数的最少的可行解。
#include <stdio.h>
struct move
{
int i,j;
}minseq[100],tempseq[100];
int refri[4][4];
int min;
bool isopen()
{
int i,j;
for (i=0;i<4;i++)
for (j=0;j<4;j++)
{
if (refri[i][j])
return false;
}
return true;
}
void reverse(int i,int j)
{
int x;
refri[i][j] = !refri[i][j];
for (x = 0;x<4;x++)
{
if (x!=j)
refri[i][x] = !refri[i][x];
if (x!=i)
refri[x][j] = !refri[x][j];
}
return ;
}
bool dfs(int cow,int col,int depth)
{ //当前已翻转次数
int i;
if (isopen())
{
if (depth < min)
{
min = depth;
for (i=0;i<depth;i++)
{
minseq[i].i = tempseq[i].i;
minseq[i].j = tempseq[i].j;
}
}
return true;
}
else
{
if (depth >= 16 || depth > min || cow > 3)
return false;
tempseq[depth].i = cow;
tempseq[depth].j = col;
reverse(cow,col);
if (col<3)
dfs(cow,col+1,depth+1); ///翻转该位后的操作
else
dfs(cow+1,0,depth+1);
reverse(cow,col);
if (col<3)
dfs(cow,col+1,depth); ///不翻转该位后的操作
else
dfs(cow+1,0,depth);
}
return false;
}
int main()
{
char temp;
int i,j;
for (i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
scanf("%c",&temp);
if (temp == '-')
refri[i][j] = 0;
else
refri[i][j] = 1;
}
getchar();
}
min = 1000000;
dfs(0,0,0);
printf("%d\n",min);
for (i=0;i<min;i++)
{
printf("%d %d\n",minseq[i].i+1,minseq[i].j+1);
}
return 0;
}
一开始做这道题,没有考虑翻转的特殊性,只是很笨的用dfs进行搜索。
相关文章推荐
- poj 2965 The Pilots Brothers' refrigerator 【dfs+枚举】【双十一大礼包】【刷题计划】
- POJ 2965 The Pilots Brothers' refrigerator(dfs+枚举 || 规律)
- ACM--枚举+DFS/巧妙思想--POJ--2965--The Pilots Brothers' refrigerator--初期算法
- (poj1.1.2)2965(The Pilots Brothers' refrigerator——DFS+枚举)
- poj 2965 枚举加dfs
- POJ2965——DFS+枚举——The Pilots Brothers' refrigerator
- poj2965(dfs暴力枚举)
- poj 1753||poj 2965 枚举+dfs
- POJ2965 状态压缩+BFS,DFS枚举,以及大牛的解法~
- poj2965(枚举||dfs)
- poj 2965 The Pilots Brothers' refrigerator(dfs 枚举 +打印路径)
- POJ 2965 The Pilots Brothers' refrigerator 枚举dfs
- POJ 2965(DFS+枚举)
- poj 2965 The Pilots Brothers' refrigerator(dfs 枚举 +打印路径)
- poj 2965 枚举+DFS
- POJ 2965 The Pilots Brothers' refrigerator(枚举+dfs)
- poj 2965 The Pilots Brothers' refrigerator——DFS(分类是枚举)
- poj2965 The Pilots Brothers' refrigerator(直接计算或枚举Enum+dfs)
- POJ 2965 The Pilots Brothers' refrigerator(枚举+DFS)
- 文章标题 POJ 2965 : The Pilots Brothers' refrigerator(枚举+dfs)