/*
重温八数码,优化算法
数据结构:一维数组。
num[i]表示第i+1行第num[i]列有元素,通过对num[i]初始化进行排列即可模拟所有格局。如:num[0]=3,表示第一行第3列有元素。
核心算法:判断是否在对角即可(横向、纵向已经在数据结构设计中避开,免去判断)
求下一排列
推广:在很多带回溯、递归的索搜,可试着用数组进行全排列并判断即可。
要点:熟悉掌握全排列算法。废话不多说,编译代码运行后逐步分析吧。
*/
#include<iostream>
using namespace std;
bool is_end(int *num,int len)
{
for(int i = 0;i<len;i++)
{
if(num[i]!=len-i-1)
return false;
}
return true;
}
bool check(int *num,int len)
{
for(int i =0;i<len-1;++i)
{
for(int j = i+1;j<len;++j)
{
if(i-j==num[i]-num[j]||j-i==num[i]-num[j])
return false;
}
}
return true;
}
void print(int *num,int len)
{
for(int i = 0;i<len;i++)
{
for(int j = 0;j<len;j++)
{
if(num[i] == j)
cout<<"☆ ";
else
cout<<"■ ";
}
cout<<endl;
}
}
void print_arrary(int *num,int len)
{
for(int i = 0;i<len;i++)
cout<<num[i];
cout<<endl;
}
int* Permutation(int *a, int n)//求n位排列a的下一个排列
{
int left = 0;
int right = 0;
int i = 1;
bool is_far = false;
left = n - 1;
while (left >= 0 && a[left-1] > a[left]) //找到 left = i = max{ i|pi-1<pi }
{
left--;
if(left == 0)
{
is_far = true;
break;
}
}
if(is_end(a,n)) //没有下一序列了.
return a;
right = n - 1;
while (a[right] < a[left-1]) //找到right = l = max{k|P(left)<Pk}
right--;
swap(a[right],a[left-1]);
right = n -1;
while (left < right)//逆置左右边界之间的元素,使其按增序排列
{
swap(a[right],a[left]);
left++;
right--;
}
return a;
}
int main()
{
const int len = 8; //数码的基数
int *num = new int[len];
int s = 1;
for(int i = 0;i<len;i++)
num[i] =i;
while(!is_end(num,len))
{
if(check(num,len))
{
printf("第%d个解为:\n",s);
print_arrary(num,len);
print(num,len);
cout<<endl;
s++;
}
num = Permutation(num,len);
}
delete num;
return 0;
}