问题描述:
请编写程序求解篮球错排问题。已知n个篮子一字排开(n为用户输入的任意正整数),从左到右分别标着号:1,2,... ...,n;每个球也有编号,分别也是1,2,... ...,n。现要将这n个球全部放入这n个篮子中,满足:每个篮子放置1个球,球的号不能与其所在的篮子的号相同,且在相邻篮子内的球的球号不能相邻。例如,如果在相邻两个篮子内的球的球号分别为9和10,则是不允许的。请输出所有符合要求的放球方式(对于每种符合要求的放球方式,都应输出在每个篮子中的球号)。
程序:
下面的解法非常好理解,其实就是一边求全排列,一边判断当前生成的全排列是否满足错排条件,若满足就输出当前的排列……
==========
#include <iostream>
using namespace std;
static int COUNT=0;
//判断当前的排列a[]是否满足错排条件
bool validate(int a[],int size)
{
//第一个是否在第一个位置、或第一个和第二个是否相邻
if (a[0]==1||a[0]==a[1]+1||a[0]==a[1]-1)
return false;
//倒数第一个是否在倒数第一个位置、或倒数第一个和倒数第二个是否相邻
if (a[size-1]==size||a[size-1]==a[size-2]+1||a[size-1]==a[size-2]-1)
return false;
//中间的是否在对应的位置上、或与其前面和后面的位置上的是否相邻
for (int i = 2;i<=size-1;i++)
{
if (a[i-1]==i||a[i-1]==a[i-2]+1||a[i-1]==a[i-2]-1||
a[i-1]==a[i]+1||a[i-1]==a[i]-1)
return false;
}
return true;
}
//对于a[]的下标为k和m间的元素进行全排列,同时输出满足错排条件的的排列
void permuta(int a[],int k,int m,int NUM)
{
if(k == m)
{
if(validate(a,NUM)) //当前排列若满足错排条件就输出
{
COUNT++;
//打印结果
for(int k=0;k<NUM;k++)
cout<<a[k]<<" ";
cout<<endl;
}
}
else
{
for(int i=k;i<=m;i++)
{
swap(a[k],a[i]);
permuta(a,k+1,m,NUM);
swap(a[k],a[i]);
}
}
}
int main()
{
int NUM;
cout<<"Input NUM: ";
cin>>NUM;
int *per = new int[NUM];
for(int i=0;i<NUM;i++)
per[i] = i+1;
permuta(per,0,NUM-1,NUM);
cout<<endl<<"the total number is :"<<COUNT<<endl;
return 0;
}