时钟问题--领会全排列算法

1.    scanf("%d%d", &a, &b)......................................................................................... 1

2.    时钟问题领会全排列的递归算法.................................................................. 1

 

1.    scanf("%d%d", &a, &b)

正确读入两个正数,返回2

否则返回0,例如等待时输入字母。

2.    时钟问题领会全排列的递归算法

现有一巨型时钟,一人站在1点处,从1点出发,顺时针往后走当前点数,如从1点出发,则走1步到达2点,然后再走2步到达4点,然后再走4步到达8点,然后再走8步又到了4点,此时他将在48之间无限循环。现假设时钟个点位置可以随意互相调动,调动后该人同样从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,将34互换,
6。得到3;输出1243
7。跳转到2,将23互换,
8。重复3-6,得13241342
9。跳转到2,将24互换,得到14231432
以下省略若干步。。
最后就得到全排列

 

#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 55 4, 即以4开头的5的全排列和以5开头的4的全排列。

由于一个数的全排列就是其本身,从而得到以上结果。

2、再看后三个数3, 4, 5。它们的全排列为3 4 53 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 = 1perm(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;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值