您的位置:首页 > 其它

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进行搜索。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  POJ dfs 枚举