题目:
随机分配座位,共n个学生,使学号相邻的同学座位不能相邻
思路:
最开始的时候还以为是个近似于n皇后的题目。后来说只要输入是纯随机的,输出一个正确的结果就可以了。第一反应自然是从头暴力随机到尾,每次输出之后检查,一旦有了和之前重复的数字或者和前一位相邻的数字就扔掉重新随机当前位置。但是这个方法第一慢第二有bug:一旦随机出这样的序列,091827364,最后一位5无法放入,需要有一个”回头“的机制。此时同学正好提到了插入排序和index数组,于是想到可以随机建立一个index数组,这样就不用向前检查重复,省去了最浪费时间的地方,接着index拖着原数组快速排序就好了。
于是这是当时定下的方案:先将0-n-1的值赋入数组中,接着建立index数组,赋值为当前位和前一位不相等或相邻的一组数。接着将index快排,原数组对位快排
以及当时的代码:
有bug的代码:

但是被同学发现了毛病如下:
一旦出现了这种情况
array初值 0 1 2 3 4 5 6 7 8 9
index 7 5 8 3 1 8 2 9 1 9
array排后 4 8 6 3 1 0 2 5 7 9
即,index的取值出现了断档,相邻两个index相差1依然不能保证他们再排序后不能相邻。最终解决办法是增加了一个校验数组,最终代码如下
代码:
1 void NoNeighbour(int *array,int n) 2 { 3 int i; 4 for(i=0;i<=n-1;++i) 5 array[i]=i;//先按0-n-1赋值 6 int *index=malloc(sizeof(int)*n);//索引数组 7 int rand_temp;//随机数暂存 8 for(i=0;i<=n-1;++i) 9 if(i!=0&&((rand_temp=rand()%n)==index[i-1]||rand_temp==index[i-1]+1||rand_temp==index[i-1]-1))//如果当前随机出来的索引数和前一位索引数相等或相邻 10 --i;//重新计算当前位置索引数 11 else 12 index[i]=rand_temp; 13 //随机生成了一个保证相邻两位之间不挨着的索引数组 14 //接着将索引数组排序,原数组保证对位移动,则原数组会变为乱序数组,并保证原相邻不相邻 15 SpecialQuickSort(array,index,0,n-1); 16 } 17 18 void SpecialQuickSort(int *array,int *index,int low,int high)//就是一个索引拖array的快排 19 { 20 if(low>=high) 21 return ; 22 int middle,current=low; 23 for(middle=low+1;middle<=high;++middle) 24 { 25 if(index[middle]<index[low]) 26 { 27 SwapInt(&index[middle],&index[++current]); 28 SwapInt(&array[middle],&array[current]); 29 } 30 } 31 SwapInt(&index[low],&index[current]); 32 SwapInt(&array[low],&array[current]); 33 34 SpecialQuickSort(array,index,low,current-1); 35 SpecialQuickSort(array,index,current+1,high); 36 } 37 38 void SwapInt(int *a,int *b) 39 { 40 int temp=*a; 41 *a=*b; 42 *b=temp; 43 }
丑陋地打了个补丁……
浙公网安备 33010602011771号