上升数列的生成算法

来源:互联网 发布:unity3d中文论坛 编辑:程序博客网 时间:2024/06/07 03:30

上升数列的生成算法

Martin Garder在《矩阵博士的魔法数》一书中给出了如下一个问题:
在12356789之间插入若干个加、减符号,使得其结果正好等于100。请找出问题全部的解。

任何两个相邻数之间可以插入+、-运算符之一,也可以不插入任何运算符。对于后一种特殊情况,我们引入一个特殊操作符$,a$b表示a、b之间不插入+、-操作符,其定义为
a$b = 10a+b
$运算满足结合律
a$(b$c)=(a$b)$c
因此多个$运算按从左至右、从右至左或其它次序将得到相同的结果。$运算的优先级比+、-运算高,且不满足交换律。
由上述定义,一个上升数列的运算式
123+4-5+6-78+9
可以表示成
1$2$3+4-5+6-7$8+9
的形式,而任何在上升数列中插入+、-运算符的算式都可以表示成下面的标准形式
1 op0 2 op1 3 op2 4 op3 5 op4 6 op5 7 op6 8 op7 9
这里opi为+、-、$之一。
~~~~~~~~~~~~~~~~~~~~~~~~~~

下面的程序枚举op0,…,op7的各种可能情形,找出运算结果等于100的表达式。由于运算会超过一个整数的表达范围,因此初始数据及中间结果均采用长整数表示。计算按从左至右的次序进行, 并考虑到$与+、-之间优先级的差异。
// File: IncSeq.C
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

struct LongIntList 
{
    long int val;
    struct  LongIntList *next;
};

struct OpList 
{
    int op;
    struct OpList *next;
};

long int Result;
FILE   *fp;

// Function prototypes
long int calc(long int num1, int op, long int num2);
void write_express(int *op,long int res);

int main(void)
{
    struct LongIntList  *numlist, *num, *num1, *num2;
    struct OpList  *oplist, *oprand, *oprand1, *oprand2;
    int   i;
    int   op[8];
    long int   res = 0;

    if ((fp = fopen("inc.dat", "w")) == NULL)
    {
      printf("/nCan't creat file inc.dat!/n");
      return 0;
    }

    printf("Please input the number you want to get:");
    scanf("%ld", &Result);

    for (op[0] = 0; op[0] < 3; op[0]++)
    for (op[1] = 0; op[1] < 3; op[1]++)
    for (op[2] = 0; op[2] < 3; op[2]++)
    for (op[3] = 0; op[3] < 3; op[3]++)
    for (op[4] = 0; op[4] < 3; op[4]++)
    for (op[5] = 0; op[5] < 3; op[5]++)
    for (op[6] = 0; op[6] < 3; op[6]++)
    for (op[7] = 0; op[7] < 3; op[7]++) 
    {
      oplist = NULL;
      for (i = 7; i >= 0; i--)
     {
     oprand = (struct OpList *)malloc(sizeof(struct OpList));
     oprand->op = op[i];
     oprand->next = oplist;
     oplist = oprand;
          }
      numlist = NULL;
      for (i = 9; i > 0; i--)
          {
     num = (struct LongIntList *)malloc(sizeof(struct LongIntList));
     num->val = (long)i;
     num->next = numlist;
     numlist = num;
          }
      oprand1 = oplist;
      oprand2 = oplist;
      num1 = numlist;
      while (oprand2)
          {
     num2 = num1->next;
     if (oprand2->op == 2) 
  {
    num1->val = calc(num1->val, oprand2->op, num2->val);
    num1->next = num2->next;
    free(num2);
    num2 = num1->next;
    if (oprand2 == oplist)
      {
          oplist = oprand2->next;
          free(oprand1);
          oprand1 = oplist;
          oprand2 = oplist;
        }
        else
      {
            oprand1->next = oprand2->next;
            free(oprand2);
            oprand2 = oprand1->next;
        }
  }
     else
  {
    if (oprand1 != oprand2) oprand1 = oprand2;
    oprand2 = oprand2->next;
    num1 = num2;
    num2 = num2->next;
  }
      }
      oprand = oplist;
      num = numlist;
      res = num->val;
      num = num->next;
      while (oprand)
     {
     res = calc(res, oprand->op, num->val);
     oprand = oprand->next;
     num = num->next;
          }

      while (oplist)
     {
     oprand = oplist->next;
     free(oplist);
     oplist = oprand;
          }
      while (numlist)
     {
     num = numlist->next;
     free(numlist);
     numlist = num;
          }
      if (res == (long)Result) write_express(op, res);
    }

    fclose(fp);
    return 1;
}

long int calc(long int num1, int op, long int num2)
{
    long int res;

    switch (op)
    {
      case 0:
   res = num1 + num2;
   break;

      case 1:
   res = num1 - num2;
   break;

      case 2:
   res = num1 * 10 + num2;
   break;
    }

    return(res);
}

void write_express(int *op, long int res)
{
    int i;

    for (i = 0; i < 8; i++) 
    {
 fprintf(fp, "%d", i+1);
 switch (op[i]) 
      {
     case 0: fprintf(fp, "+"); break;
     case 1: fprintf(fp, "-"); break;
     case 2: break;
 }
    }
    fprintf(fp, "9=%ld/n", res);
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~

计算结果如下:
1+2+3-4+5+6+78+9=100
1+2+34-5+67-8+9=100
1+23-4+5+6+78-9=100
1+23-4+56+7+8+9=100
12+3+4+5-6-7+89=100
12+3-4+5+67+8+9=100
12-3-4+5-6+7+89=100
123+4-5+67-89=100
123+45-67+8-9=100
123-4-5-6-7+8-9=100
123-45-67+89=100
 

原创粉丝点击