一道简单题的思考
一道简单题的思考
今天我同学去交C语言的实验报告,熊壮出的题,有道题拿给我看了下,第一个实验有这么一道题:
一个两行三列的矩阵,存六个数:1-6,保证左边比右边大,上面比下面大,输出所有可能的情况。
寥寥数语,看起很简单的样子,但是我仔细一想,竟然感觉有点回溯的影子,于是按八皇后的写法写了段代码:
#include <iostream>
using namespace std;
#define I 5
#define J 6
int num[I][J];
bool flag[I*J+1];
void Display()
{
for (int i=0;i<I;i++)
{
for (int j=0;j<J;j++)
{
cout<<num[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
system("pause");
}
bool Search(int m,int i)
{
if (m==0)
return true;
if (m<J)
{
if (i>=num[m/J][m%J-1])
return false;
else
return true;
}
else
{
if (m%J==0)
{
if (i>=num[m/J-1][0])
return false;
else
return true;
}
else
{
if (i>=num[m/J-1][m%J] || i>=num[m/J][m%J-1])
return false;
else
return true;
}
}
}
void Foo(bool flag[],int m)
{
if (m==I*J)
{
Display();
return;
}
else
{
for (int i=I*J;i>0;i--)
{
if (!flag[i])
{
if (Search(m,i))
{
num[m/J][m%J] = i;
flag[i] = true;
Foo(flag,m+1);
}
}
}
}
}
int main()
{
memset(num,0,sizeof num);
memset(flag,false,sizeof flag);
Foo(flag,0);
return 0;
}
using namespace std;
#define I 5
#define J 6
int num[I][J];
bool flag[I*J+1];
void Display()
{
for (int i=0;i<I;i++)
{
for (int j=0;j<J;j++)
{
cout<<num[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
system("pause");
}
bool Search(int m,int i)
{
if (m==0)
return true;
if (m<J)
{
if (i>=num[m/J][m%J-1])
return false;
else
return true;
}
else
{
if (m%J==0)
{
if (i>=num[m/J-1][0])
return false;
else
return true;
}
else
{
if (i>=num[m/J-1][m%J] || i>=num[m/J][m%J-1])
return false;
else
return true;
}
}
}
void Foo(bool flag[],int m)
{
if (m==I*J)
{
Display();
return;
}
else
{
for (int i=I*J;i>0;i--)
{
if (!flag[i])
{
if (Search(m,i))
{
num[m/J][m%J] = i;
flag[i] = true;
Foo(flag,m+1);
}
}
}
}
}
int main()
{
memset(num,0,sizeof num);
memset(flag,false,sizeof flag);
Foo(flag,0);
return 0;
}
其中用flag标志数组是为了解决数字重复和重复计算的问题,感觉跟DP似的,呵呵
但是感觉很奇怪,回溯应该算比较麻烦的了吧,当时学C的时候有可能用这种方法么?难道有更简单的方法?最近刷POJ都有一种很奇怪的感觉,感觉自己的代码傻兮兮的,好像是最笨的方法一样,总感觉有比我写的代码好N倍的代码.以前怎么没有这种感觉.。