zoukankan      html  css  js  c++  java
  • C语言-回溯例3

                   排列问题

    1、实现排列A(n,m)
    对指定的正整数m,n(约定1<m<=n),具体实现排列A(n,m)。
    2、 回溯算法设计
    设置一维数组a,a(i)(i=1,2,…,m)在1—n中取值。首先从a(1)=1开始,逐步给a(i)(1≤i≤m)赋值,每一个a(i)赋值从1开始递增至n。
    为判断数字是否重复,设置中间变量g:先赋值g=1;若出现某两数字相同(即a(i)=a(j)),则赋值g=0(重复标记)。
    若i=m与g=1同时满足,则为一组解,用s统计解的个数后,格式打印输出这组解。
    若i<m 且g=1,表明不到m个数字,下一个a(i)从1开始赋值,继续。
    若a(i)=n ,则返回前一个数组元素a(i-1)增1赋值。直到a(1)=9时,已无法返回,意味着已全部试毕,求解结束。

    3、算法描述
    输入正整数n,m,(n≥m);
    i=1;a[i]=1;
    while (1)
    { g=1;for(j=1;j<i;j++)
      if(a[j]==a[i] ) g=0;    /* 检测,不满足返回 */
      if(g && i==m)
         printf(a[1-m]);       /* 输出一个解 */
      if(i<n && g) {i++;a[i]=1;continue;}
      while(a[i]==n && i>1) i--;   /* 回溯 */
      if(a[i]==n && i==1) break;  /* 退出循环,结束 */
      else a[i]=a[i]+1;
    }

    4、代码实现

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 int main()
     5 {
     6     int a[100];
     7     int num;
     8     int flag;
     9     int i,j,k;
    10     int m,n;
    11     printf("输入n(A(n,m)):");
    12     scanf("%d",&n);
    13     printf("输入m(A(n,m)):");
    14     scanf("%d",&m);
    15     i=1;
    16     a[i]=1;
    17     num=0;
    18     while(1)
    19     {
    20         flag=1;
    21         for(k=i-1;k>=1;k--)
    22         {
    23             if(a[i]==a[k])
    24             {
    25                 flag=0;
    26             }
    27         }
    28         if(flag&&i==m)
    29         {
    30             num++;
    31             for(j=1;j<=m;j++)
    32             {
    33                 printf("%d",a[j]);
    34             }
    35             printf(" ");
    36             if(num%6==0)
    37             {
    38                 printf("
    ");
    39             }
    40         }
    41         if(flag&&i<n)
    42         {
    43             i++;
    44             a[i]=1;
    45             continue;
    46         }
    47         while(a[i]==n&&i>1)i--;
    48         if(a[i]==n&&i==1)
    49         {
    50             break;
    51         }
    52         else
    53         {
    54             a[i]++;
    55         }
    56     }
    57     printf("
    排列数A(%d,%d)=%d",n,m,num);
    58     return 0;
    59 }

    运行结果:

    5、扩展

    (1)把以上程序中的输出语句printf("%d",a[j])改为printf("%c",a[j]+64);排列(或组合)输出由前n个正整数改变为前n个大写英文字母输出。

    运行结果:

    (2)把以上程序中的输出语句printf("%d",a[j])改为printf("%c",n+65-a[j]);排列(或组合)输出由前n个正整数改变为前n个大写英文字母逆序输出。

    运行结果:

  • 相关阅读:
    C#中|(位或)和||(逻辑或)
    VS快捷键(转)
    C# 3.0 新特性 学习(二):匿名类型、扩展方法
    Highcharts 如何添加基准线
    怎样用Diskpart进行分区
    命名空间别名限定符 (::)
    NDK下 将Platinum SDK 编译成so库 (android upnp)
    在native线程利用JNI 反射自定义类
    GithubClient(ANDROID)开源之旅(一) 初探GitHub
    基于Platinum库的DMR实现(android)
  • 原文地址:https://www.cnblogs.com/xiaojingang/p/3746836.html
Copyright © 2011-2022 走看看