2. 时钟问题—领会全排列的递归算法.................................................................. 1
1. scanf("%d%d", &a, &b)
正确读入两个正数,返回2
否则返回0,例如等待时输入字母。
2. 时钟问题—领会全排列的递归算法
现有一巨型时钟,一人站在1点处,从1点出发,顺时针往后走当前点数,如从1点出发,则走1步到达2点,然后再走2步到达4点,然后再走4步到达8点,然后再走8步又到了4点,此时他将在4和8之间无限循环。现假设时钟个点位置可以随意互相调动,调动后该人同样从1点出发(此时1点不一定在原来的标准1点处),按先前规律前进,如果该人能够到达所有点,即此调动方式成功。请写程序列出所有能够成功的调动情况。
#include "stdio.h"
int a[13];
int n=12;
int c=0;
int perm(int k)
{
int p,t,j,q,count;
if(k==n)
{
for (p=1;p<=k;p++)
{
if(a[p-1]==1)
{q=p-1;
break;
}
}
count=0;
while(a[q]!=12&&count<11)
{
q=(a[q]+q)%12;
count++;
}
if(count==11&&a[q]==12)
{
printf("find it!:");
for(p=1;p<=k;p++) printf("%d ",a[p-1]);
printf("/n");
}
else
return 0;
}
for(j=k;j<=n;j++)
{t=a[k-1];a[k-1]=a[j-1];a[j-1]=t;
perm(k+1);
t=a[k-1];
a[k-1]=a[j-1];a[j-1]=t;}
}
int main()
{
int i,j,k;
a[0]=12;
a[1]=1;
for (i=2;i<12;i++)
a[i]=i;
perm(1);
printf("the end/n");
return 0;
}
其中最重要的算法是全排列的递归算法,一定要理解
先控制一个不动,让剩余的排列好,然后再移动第一个,再排列好剩余的
这个程序也是这个意思
举个例子说 1234
1。先保持1不动,排列234
2。保持2不动,排列34
3。保持3不动,排列4
4。得到4;输出1234。
5。然后跳转到3,将3与4互换,
6。得到3;输出1243。
7。跳转到2,将2与3互换,
8。重复3-6,得1324,1342。
9。跳转到2,将2与4互换,得到1423,1432。
以下省略若干步。。
最后就得到全排列
#include <stdio.h>
void permutation(char a[], int m, int n) //n的前m位不动
{
int i;
char t;
if (m<n-1)
{
permutation(a, m+1, n);
for (i=m+1;i<n;i++)
{
t=a[m]; a[m]=a[i]; a[i]=t;
permutation(a, m+1, n);
t=a[m]; a[m]=a[i]; a[i]=t;
}
} else
{
printf("%s ", a);
}
}
int main()
{
char a[]="12345";
permutation(a, 3,5);
return 0;
}
还有一种:其实这种就是多了一个自己与自己换的过程,其实效率不高
全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。现以{1, 2, 3, 4, 5}为
例说明如何编写全排列的递归算法。
1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。
由于一个数的全排列就是其本身,从而得到以上结果。
2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。
即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.
从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。
因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。
为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列。
算法如下:
#include <stdio.h>
int n = 0;
void swap(int *a, int *b)
{
int m;
m = *a;
*a = *b;
*b = m;
}
void perm(int list[], int k, int m)
{
int i;
if(k > m)
{
for(i = 0; i <= m; i++)
printf("%d ", list[i]);
printf("/n");
n++;
}
else
{
for(i = k; i <= m; i++)
{
swap(&list[k], &list[i]);
perm(list, k + 1, m);
swap(&list[k], &list[i]);
}
}
}
int main()
{
int list[] = {1, 2, 3, 4, 5};
perm(list, 0, 4);
printf("total:%d/n", n);
return 0;
}