温故而知新,常来复习哦!
一天了呀,费了九牛二虎之力,终于有了一丝进展,相信自己,一步一步往前走!经过‘参考借鉴’,代码如下:
//翻棋子
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int l[4][4];
//int min=0x7fffffff;
int check()
{
int i,j;
for(i=0;i<4;++i){
for(j=0;j<4;++j){
if(l[i][j]!=l[0][0]){
return -1;
}
}
}
return 1;
}
void turn(int m,int n){
l[m][n]=!l[m][n];
if(m-1>=0){
l[m-1][n]=!l[m-1][n];
}
if(m+1>=0){
l[m+1][n]=!l[m+1][n];
}
if(n-1>=0){
l[m][n-1]=!l[m][n-1];
}
if(n+1>=0){
l[m][n+1]=!l[m][n+1];
}
}
void dfs(int s,int M){
int Min=0x7fffffff;
int x,y;
if(s==16){
if(check()==1)
if(M<Min){
Min=M;
}
return;
}
else{
x=s/4;
y=s%4;
dfs(s+1,M);
turn(x,y);
dfs(s+1,M+1);
turn(x,y);
}
}
int main()
{
char p;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
scanf("%c",&p);
if(p=="b") l[i][j]=0;
else l[i][j]=1;
}
}
dfs(0,0);
if(Min==0x7fffffff){
printf("Impossible\n");
}
else{
printf("%d\n",Min);
}
return 0;
}
但是还有错误暂时没有解决,我琢磨着先问着别人,在这里做个总结:
1.在每一个 if语句,while语句,for语句后面老老实实加上大括号,注意层次
2.一开始设置了变量 min ,但是报错:
[Error] overloaded function with no contextual type information
原因是与C++的内置函数 min 重名了,所以不要设置与C++内置函数重名的变量名
3.第一个是检查函数,以左上角状态为参照,return -1 为一个约定俗成的惯例,表示该函数失败了,类推 return 1 则函数成功了
4.第二个定义翻转函数,用 !变量 实现,用判断语句避免了边界情况
***5.***我还不是很理解,第三个定义深搜,深度优先搜索,大体的意思是从某一个未被遍历的位置出发,找到与之相邻的未被遍历的点,依次进行下去直到找不到相邻的未被遍历过的点,从而原路退一步,继续搜索相邻的未被遍历过的点(可能一个点周围有多个未被遍历过的点,而一次只能找到一个),搜索到了就往深处进行,找不到了就继续后退,直到退回原处,然后进行检查,如果所有的点都被遍历了,就完成了,反之再从某一个未被遍历过的点出发重复一开始的操作,直到所有的点都被遍历过。。再附一个比较专业的文章吧:
深度优先搜索
此题的遍历方式是从左往右,从上往下,巧妙运用了整除号与取余符号遍历每一行的每一列,但是我不很明白其中迭代的含义,哪位大佬能解答一下吗?小弟真的感激不尽!
6.最后让我们看一看我们的报错:
if(p==“b”) l[i][j]=0; 报错,但我不理解为什么
if(Min==0x7fffffff) 同样不清楚为什么错,我很奇怪,怎么让这个 Min 在其它的函数中被调用呢?
写到这里,说真的,我想先把这道题放一放吧,就我的水平来看要想将它完全搞懂真的比较困难,怪我自己学术不精了,但是,做人要乐观,即使是错误的,也要大胆的展示出来,因为,这只是我未来成功路上的垫脚石而已,我有朝一日会蔑视这道题的!
看一个大佬的代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int a[4][4];
int Min=0x7fffffff;
int check()//检查棋子是否同色
{
int i,j;
for(i=0; i<4; ++i)
for(j=0; j<4; ++j)
if(a[i][j]!=a[0][0])
return -1;
return 1;
}
void change(int i,int j){
a[i][j]=!a[i][j];
if(i-1>=0){
a[i-1][j]=!a[i-1][j];
}
if(j-1>=0){
a[i][j-1]=!a[i][j-1];
}
if(i+1<4){
a[i+1][j]=!a[i+1][j];
}
if(j+1<4){
a[i][j+1]=!a[i][j+1];
}
}
void dfs(int d,int k)
{
int x,y;
if(d==16){
if(check()==1)
if(k<Min)
Min=k;
return;
}else{
x=d/4;//行
y=d%4;//列
dfs(d+1,k);
change(x,y); //翻过去
dfs(d+1,k+1);
change(x,y); //别忘了翻回去,这个是返回原来的状态
}
}
int main()
{
char t;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
cin>>t;
if(t=='b') a[i][j]=0;
else a[i][j]=1;
}
}
dfs(0,0);
if(Min==0x7fffffff)
cout<<"Impossible"<<endl;
else
cout<<Min<<endl;
return 0;
}
//转自flip game
我不清楚为什么我的就不行了呢,差不了多少啊!
又思考了一下:改为如下:
//翻棋子
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int l[4][4];
int Min=0x7fffffff;
//最大的十六进制数
//还是要定义在外面!解决第一个错误
int check()
{
int i,j;
for(i=0;i<4;++i){
for(j=0;j<4;++j){
if(l[i][j]!=l[0][0]){
return -1;
}
}
}
return 1;
}
void turn(int m,int n){
l[m][n]=!l[m][n];
if(m-1>=0){
l[m-1][n]=!l[m-1][n];
}
if(m+1>=0){
l[m+1][n]=!l[m+1][n];
}
if(n-1>=0){
l[m][n-1]=!l[m][n-1];
}
if(n+1>=0){
l[m][n+1]=!l[m][n+1];
}
}
void dfs(int s,int M){
int x,y;
if(s==16){
if(check()==1){
if(M<Min){
Min=M;
}
}
return;
}
else{
x=s/4;
y=s%4;
dfs(s+1,M);
turn(x,y);
dfs(s+1,M+1);
turn(x,y);
}
}
int main()
{
char p;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
scanf("%c",&p);
if(p=='b') l[i][j]=0;
else l[i][j]=1;
}
}
dfs(0,0);
if(Min==0x7fffffff){
printf("Impossible\n");
}
else{
printf("%d\n",Min);
}
return 0;
}
先搞懂两件事:
1.i++ 与 ++i 的区别
比较好理解,就不赘述了:
C语言 i++ 与 ++i 的区别
2.单引号与双引号
一句话,但我不知道:
单引号:字符,上面报错的原因也在于此,我用成了双引号
双引号:字符串类型
但是!
输入测试样例结果为8!而正确结果是4啊,我的自信回来了,别急!让我们慢慢来看
找到了:将
if(m-1>=0){
l[m-1][n]=!l[m-1][n];
}
if(m+1>=0){
l[m+1][n]=!l[m+1][n];
}
if(n-1>=0){
l[m][n-1]=!l[m][n-1];
}
if(n+1>=0){
l[m][n+1]=!l[m][n+1];
}
改为
if(m-1>=0){
l[m-1][n]=!l[m-1][n];
}
if(m+1<4){
l[m+1][n]=!l[m+1][n];
}
if(n-1>=0){
l[m][n-1]=!l[m][n-1];
}
if(n+1<4){
l[m][n+1]=!l[m][n+1];
}
理解错误,左右都不能超范围啊!
但是!
输出:
Impossible
还是有问题呀!继续DEBUG!
现在我们的代码是这样:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int l[4][4];
int Min=0x7fffffff;
//还是要定义在外面!解决第一个错误
int check()
{
int i,j;
for(i=0;i<4;++i){
for(j=0;j<4;++j){
if(l[i][j]!=l[0][0]){
return -1;
}
}
}
return 1;
}
void turn(int m,int n){
l[m][n]=!l[m][n];
if(m-1>=0){
l[m-1][n]=!l[m-1][n];
}
if(m+1<4){
l[m+1][n]=!l[m+1][n];
}
if(n-1>=0){
l[m][n-1]=!l[m][n-1];
}
if(n+1<4){
l[m][n+1]=!l[m][n+1];
}
}
void dfs(int s,int M){
int x,y;
if(s==16){
if(check()==1){
if(M<Min){
Min=M;
}
}
return;
}
else{
x=s/4;
y=s%4;
dfs(s+1,M);
turn(x,y);
dfs(s+1,M+1);
turn(x,y);
}
}
int main()
{
char p;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
scanf("%c",&p);
if(p=='b') l[i][j]=0;
else l[i][j]=1;
}
}
dfs(0,0);
if(Min==0x7fffffff){
printf("Impossible\n");
}
else{
printf("%d\n",Min);
}
return 0;
}
大写的
WHY??
容我休息一下继续想!!
越努力越幸运!
虽然我现在一无所知!
但我相信经过自己的努力我可以越来越好!!
等待自己 D E B U G !!!
等我元气归来,哼!
/
我渐渐意识到,这不是哪里出了错误!还是代码有问题吧!我对代码与答案代码进行了比较,重点对不同之处进行分析,
我们输出 l 看一看:
0x4ac040
竟然不是 0 1 数组!我又晕了,哪里的问题呢啊啊啊~
原来这是16进制,吓我这条菜狗一跳!通过对比,l 输出已经出现了问题,正确答案输出 l :
0x4a7040
哎~我就改了下输入输出的格式,怎么就解决了呢?!不理解!
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int l[4][4];
int Min=0x7fffffff;
//还是要定义在外面!解决第一个错误
int check()
{
int i,j;
for(i=0;i<4;++i){
for(j=0;j<4;++j){
if(l[i][j]!=l[0][0]){
return -1;
}
}
}
return 1;
}
void turn(int m,int n){
l[m][n]=!l[m][n];
if(m-1>=0){
l[m-1][n]=!l[m-1][n];
}
if(m+1<4){
l[m+1][n]=!l[m+1][n];
}
if(n-1>=0){
l[m][n-1]=!l[m][n-1];
}
if(n+1<4){
l[m][n+1]=!l[m][n+1];
}
}
void dfs(int s,int M){
int x,y;
if(s==16){
if(check()==1){
if(M<Min){
Min=M;
}
}
return;
}
else{
x=s/4;
y=s%4;
dfs(s+1,M);
turn(x,y);
dfs(s+1,M+1);
turn(x,y);
}
}
int main()
{
char p;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
cin>>p;
if(p=='b') l[i][j]=0;
else l[i][j]=1;
}
}
dfs(0,0);
if(Min==0x7fffffff){
cout<<"Impossible"<<endl;
}
else{
cout<<Min<<endl;
}
return 0;
}
(定睛一看成了改了字母的答案~哎·!!)
但是是为什么呢?
两种输入输出方式值得我去研究一下!!!
越努力越幸运!
和ZDZ一起加油鸭!