题目链接http://poj.org/problem?id=2965
此题与1753类似,同样用dfs枚举,学长学姐们应该就是想让我们先练一下这些基础吧。。
思路几乎来说都一样,不赘述了。
但是TLE了大半天,太弱了orz。。。
问题在于我用了跟1753一样的方法,将这种情况下的所有点找到才一起翻转,,这样就会出现一个问题,那么就是比如选五个点 0 1 2 3 4 5 找到后一起翻,之后选到0 1 2 3 4 6,也是找到后一起翻,,然后这样0 1 2 3 4 这几个点都重复翻,,想了一下这样导致做了很多的无用功,真该TLE。。。之前想了好久不知道怎么改,最后想到在找到点的时候就直接翻转,不要这个点的时候再翻回来。。这样就不会有那么多无用功。。比如0 1 2 3 4 每个找出来后都直接翻了,那么最后一个放5 或者6等其他的都不会再翻前面的,与之前相比大大缩短了时间。。
#include<stdio.h>
#include<string.h>
char s[20];
int a[20];
int visit[20],ans[20];
int flag=0;
int is_win()
{
int i;
for(i=0;i<16;i++)
if(a[i]==0) return 0;
return 1;
}
void flip(int depth)
{
int i,j,k,n;
int x=ans[depth]/4;
int y=ans[depth]%4;
for(j=0;j<16;j++)
if(j/4==x||j%4==y) a[j]=!a[j];
}
void dfs(int depth,int start,int r)
{
int i,n;
if(flag==1)
return ;
if(depth==r)
{
flag=is_win();
if(flag)
{
printf("%d\n",depth);
for(i=0;i<depth;i++)
printf("%d %d\n",ans[i]/4+1,ans[i]%4+1);
}
return ;
}
else
for(i=start;i<=16-r+depth;i++)
{
if(!visit[i])
{
visit[i]=1;
ans[depth]=i; //保存需要翻的点
flip(depth); //选取这个位置翻转
dfs(depth+1,i+1,r);
flip(depth); //将这个位置翻回来
visit[i]=0;
}
}
}
int main ()
{
int i,j,r;
flag=0;
memset(visit,0,sizeof(visit));
for(i=0;i<16;i++)
{
char ch;
ch=getchar();
if(ch=='\n') i--;
else s[i]=ch;
if(s[i]=='+') a[i]=0;
else a[i]=1;
}
if(is_win()) printf("0\n");
else
for(i=1;i<=16;i++)
{
memset(ans,0,sizeof(ans));
dfs(0,0,i);
if(flag==1) break;
}
return 0;
}
别人写的二维数组的dfs,值得我学习,确实这方面还很弱。附上链接http://blog.csdn.net/lyy289065406/article/details/6642597
下面是链接中的代码
/*代码一:DFS+Enum*/
//Memory Time
//240K 641MS
//本题由于要输出每次翻转的棋子,因此不适宜用BFS,应该使用DFS输出完整路径
#include<iostream>
using namespace std;
bool lock[10][10]={false};
bool flag;
int step;
int ri[16],cj[16];
bool isopen(void)
{
for(int i=3;i<7;i++)
for(int j=3;j<7;j++)
if(lock[i][j]!=true)
return false;
return true;
}
void flip(int row,int col) //其实参考POJ1753的翻棋方法也是可以做出来的,但是会超时不通过
{ //超时的原因就是翻棋时有太多多余的操作
lock[row][col]=!lock[row][col]; //POJ1753使用6x6矩形,多余操作只有周围的“一圈”翻棋!
for(int i=3;i<=6;i++) //这里使用10x10矩形,多余操作有“三圈”翻棋!
lock[i][col]=!lock[i][col]; //其实用位运算就可以只使用4x4矩形,大大降低时间复杂度,根本没有多余操作,但是程序会很复杂,不好看
for(int j=3;j<=6;j++)
lock[row][j]=!lock[row][j];
return;
}
void dfs(int row,int col,int deep)
{
if(deep==step)
{
flag=isopen();
return;
}
if(flag||row==7)return;
flip(row,col);
ri[deep]=row;
cj[deep]=col;
if(col<6)
dfs(row,col+1,deep+1);
else
dfs(row+1,3,deep+1);
flip(row,col);
if(col<6)
dfs(row,col+1,deep);
else
dfs(row+1,3,deep);
return;
}
int main(void)
{
char temp;
int i,j;
for(i=3;i<7;i++)
for(j=3;j<7;j++)
{
cin>>temp;
if(temp=='-')
lock[i][j]=true;
}
for(step=0;step<=16;step++)
{
dfs(3,3,0);
if(flag)break;
}
cout<<step<<endl;
for(i=0;i<step;i++)
cout<<ri[i]-2<<' '<<cj[i]-2<<endl;
return 0;
}