constant的小屋

软件工人有力量! 不消沉,不懈怠,积极工作,努力学习,就是***受排挤、处逆境时的态度。

导航

c++入门必做题答案

个人感觉入门必做题目还是比较有深度的,我正在不断的做,我会不断把我做的题目都粘贴到这里,供朋友们学习,欢迎高手指点不足之处,不胜感谢。

 

 


/*******************************************************************************
    FUNCTIONS IMPLEMENT
*******************************************************************************/
/*
  1.  给定等式  A B C D E     其中每个字母代表一个数字,且不同数字对应不
                    D F G     同字母。编程求出这些数字并且打出这个数字的
             +      D F G     算术计算竖式。

             ───────

                X Y Z D E
*/
//==============================================================================
// question1
//==============================================================================
void question1()
{
 int a, b, c, d, e, f, g, x, y, z;
 g = 0;//可以直接肯定的值
 f = 5;
 b = 9;
 y = 1;
 // d必须大于6,6+6+8 才能进位2,z!=0 因此 d=7or8, c=7or8,c!=d=>cd=78or87
 for ( int i = 2; i <= 6; i++ )
 {
  if ( i == 5 )
  {
   continue;
  }
  a = i;
  for ( int j = 7; j <= 8; j++ )
  {
   c = j;
   d = 8;
   z = 4;//这里我忘记了进位,也算错了z的值,感谢网友指正
   x = a + 1;
   if ( c != 7)
   {
    d = 7;
    z = 3;//这里我忘记了进位,也算错了z的值,感谢网友指正
   }
   for ( int k = 2; k <= 6; k++ )
   {
    if ( k == 5 )
    {
     continue;
    }
    e = k;
    if ( a != e && a != z &&
      e != z && e != x &&
      x != z && x != 5 && x != 7
      )
    {
     cout << "the result is:\n";
     cout << "a = " << a << "\n";
     cout << "b = " << b << "\n";
     cout << "c = " << c << "\n";
     cout << "d = " << d << "\n";
     cout << "e = " << e << "\n";
     cout << "f = " << f << "\n";
     cout << "g = " << g << "\n";
     cout << "x = " << x << "\n";
     cout << "y = " << y << "\n";
     cout << "z = " << z << "\n" << endl;
    }
   }
  }
 }

 return;
}
/*
  2. A、B、C、D、E五名学生有可能参加计算机竞赛,根据下列条件判断哪些
  人参加了竞赛:

   (1)A参加时,B也参加;

   (2)B和C只有一个人参加;

   (3)C和D或者都参加,或者都不参加;

   (4)D和E中至少有一个人参加;

   (5)如果E参加,那么A和D也都参加。
*/
//==============================================================================
// question2
//==============================================================================
void question2()
{
 // 参加是1,不参加是0
 for ( unsigned int a = 0; a <= 1; a++ )
 {
  for ( unsigned int b = 0; b <= 1; b++ )
  {
   for ( unsigned int c = 0; c <= 1; c++ )
   {
    unsigned int d = 1;//e参加将导致问题2
    // 条件 1 2 3
    if (  ( !( a - b == 1 ) ) && ( b ^ c ) && ( !( c ^ d ) ) )
    {
     cout << " 参加人员:";
     if ( a == 1)
     {
      cout << "a";
     }
     if ( b == 1)
     {
      cout << "b";
     }
     if ( c == 1)
     {
      cout << "c";
     }
     if ( d == 1)
     {
      cout << "d";
     }
     cout << "\n" << endl;
    }   
   }
  }
 }
 return;
}
/*
  3. 打印一个 N*N 的方阵,N为每边           N=15  打印出下面图形
 字符的个数(3<N<20), 要求最               TTTTTTTTTTTTTTT
 外一层为"T", 第二层为"J", 从第三层               TJJJJJJJJJJJJJT
 起每层依次打印数字 1,2,3,...                     TJ11111111111JT
 (右图以N为15为例)                           TJ12222222221JT
                                                  TJ12333333321JT
                                                  TJ12344444321JT
                                                  TJ12345554321JT
                                                  TJ12345654321JT
                                                  TJ12345554321JT
                                                  TJ12344444321JT
                                                  TJ12333333321JT
                                                  TJ12222222221JT
                                                  TJ11111111111JT
                                                  TJJJJJJJJJJJJJT
                                                  TTTTTTTTTTTTTTT
*/
//==============================================================================
// question3
//==============================================================================
void question3()
{//思路是方形矩阵,每一圈的文字一样,因此可以不断向内画圈
 const int N = 22;
 char a[N][N];
 char cht = 'T';
 char chj = 'J';
 char chnum = '1';
 int line;
 for ( line = 0; line < N; line++ )//画圈
 {
  a[0][line] = cht;
  a[N - 1][line] = cht;
  a[line][0] = cht;
  a[line][N - 1] = cht;
 }
 for ( line = 1; line < N - 1; line++ )//画圈
 {
  a[1][line] = chj;
  a[N - 2][line] = chj;
  a[line][1] = chj;
  a[line][N - 2] = chj;
 }
 if ( N == 4 )//只有T和J,输出
 {
  for ( int j = 0; j < N; j++ )
  {
   for ( int i = 0; i < N; i++ )
   {
    cout << a[i][j] << "  ";
   }
   cout << "\n" << endl;
  }
  cout << "\n" << endl;
  return;
 }
 for ( int i = 2; i < N - 2; i++ )//不断向内画圈
 {
  for ( line = i; line < N - i; line++ )//画第i个圈
  {
   a[i][line] = chnum + i - 2;
   a[N - 1 - i][line] = chnum + i - 2;
   a[line][i] = chnum + i - 2;
   a[line][N - 1 - i] = chnum + i - 2;
  }
 }
 for ( int j = 0; j < N; j++ )//输出
 {
  for ( int i = 0; i < N; i++ )
  {
   cout << a[i][j] << "  ";
  }
  cout << "\n" << endl;
 }
 return;
}
/*
  4. 在N行N列的数阵中, 数K(1〈=K〈=N)在每行和每列中出现且仅
  出现一次,这样的数阵叫N阶拉丁方阵。例如下图就是一个五阶拉丁方阵。
  编一程序,从键盘输入N值后,打印出所有不同的N阶拉丁方阵,并统计个数。

        1  2  3  4  5
        2  3  4  5  1
        3  4  5  1  2
        4  5  1  2  3
        5  1  2  3  4
*/
//==============================================================================
// question4
//==============================================================================
void question4()
{//思路,用环形队列来构建数据,不断变换队列的起始位置来显示
 const int N = 39;//you can modify it
 struct question
 {
 public:
  int num;
  question* next;
 };
 // construct circle link
 question* header = new question;
 header->num = 1;
 header->next = NULL;
 question* tempheader = header;
 for ( int i = 1; i < N; i++ )
 {
  question* temp = new question;
  temp->num = i + 1;
  temp->next = NULL;
  tempheader->next = temp;
  tempheader = temp;
 }
 tempheader->next = header;
 // display array
 tempheader = header;
 for ( int j = 0; j < N; j++)
 {
  for ( int i = 0; i < N; i++ )
  {
   cout << tempheader->num << "  ";
   tempheader = tempheader->next;
  }
  cout << endl;
  tempheader = tempheader->next;
 }
 // delete link
 for ( int k = 0; k < N; k++ )
 {
  tempheader = header->next;
  delete header;
  header = tempheader;
 }
 return;
}
/*
  5. 输入一个十进数,将其转换成 N 进制数(1<N<=16)。
*/
//==============================================================================
// question5
//==============================================================================
void question5( int aNumber, int aFormat )
{
 if ( aNumber >= ( 2 << 10 ) || aNumber < 0 )
 {
  cout << "can not suport this number, please input 0 ~ 2^10" << endl;
  return;//这里不允许用户输入太大的值
 }
 char output[10];
 // 可用sum = 1step + 2step * 10 + 3sted* 100...power *= 10的方式,
 // 减少大小限制,COUT << SUM
 for ( int i = 0; i < 10; i++)
 {
  output[i] = 0;
 }
 int mod = 0;
 int index = 0;
 int distancevalue = 1 - '1';// 输出为字符序列,数字需要转换成数字字符
 while ( 1 )
 {
  mod = aNumber % aFormat;
  aNumber /= aFormat;
  switch( mod )
  {
  case 15:
   {
    output[index] = 'F';
    break;
   }
  case 14:
   {
    output[index] = 'E';
    break;
   }
  case 13:
   {
    output[index] = 'D';
    break;
   }
  case 12:
   {
    output[index] = 'C';
    break;
   }
  case 11:
   {
    output[index] = 'B';
    break;
   }
  case 10:
   {
    output[index] = 'A';
    break;
   }
  default:
   {
    output[index] = mod - distancevalue;// 数字转换成数字字符
    break;
   }
  }  
  if ( aNumber == 0 )
  {
   break;
  }
  index++;
 }
 // display
 for ( int j = index; j >= 0; j-- )
 {
  cout << output[j];
 }
 cout << endl;
 return;
}
/*
 6. 矩阵中填数. 当给出 N*N 的矩阵,要求用程序填入下列形式的数:

   ① 倒填,例如N=5             ② 蛇形填数              ③ 回转填数

 ┌─┬─┬─┬─┬─┐   ┌─┬─┬─┬─┬─┐   ┌─┬─┬─┬─┬─┐
 │25│24│23│22│21│   │ 1│ 3│ 4│10│11│   │ 1│16│15│14│13│
 ├─┼─┼─┼─┼─┤   ├─┼─┼─┼─┼─┤   ├─┼─┼─┼─┼─┤
 │20│19│18│17│16│   │ 2│ 5│ 9│12│19│   │ 2│17│24│23│12│
 ├─┼─┼─┼─┼─┤   ├─┼─┼─┼─┼─┤   ├─┼─┼─┼─┼─┤
 │15│14│13│12│11│   │ 6│ 8│13│18│20│   │ 3│18│25│22│11│
 ├─┼─┼─┼─┼─┤   ├─┼─┼─┼─┼─┤   ├─┼─┼─┼─┼─┤
 │10│ 9│ 8│ 7│ 6│   │ 7│14│17│21│24│   │ 4│19│20│21│10│
 ├─┼─┼─┼─┼─┤   ├─┼─┼─┼─┼─┤   ├─┼─┼─┼─┼─┤
 │ 5│ 4│ 3│ 2│ 1│   │15│16│22│23│25│   │ 5│ 6│ 7│ 8│ 9│
 └─┴─┴─┴─┴─┘   └─┴─┴─┴─┴─┘   └─┴─┴─┴─┴─┘
*/
//==============================================================================
// question6
//==============================================================================
void question6()
{
 // the first is too easy
 // the third
 const int N = 4;
 int m(0), n(0), i(0), j(0), k(0);
 int a[N][N];
 int num = 1;
 while ( k < ( N + 1 ) / 2 )//不断的画圈
 {
  m = k;
  n = k;
  for ( ; m < N - k; m++ )//第x列,从上到下
  {
   a[m][n] = num;
   num++;
  }
  m--;
  n++;
  for ( ; n < N - k; n++ )//第x列,从左到右
  {
   a[m][n] = num;
   num++;
  }
  m--;
  n--;
  for ( ; m >= k; m-- )//第x列,从下到上
  {
   a[m][n] = num;
   num++;
  }
  m++;
  n--;
  for ( ; n > k; n-- )//第x列,从右到左
  {
   a[m][n] = num;
   num++;
  }
  k++;
 }

// display
 for ( i = 0; i < N; i++)
 {
  for ( j = 0; j < N; j++ )
  {
   cout << a[i][j] << "  ";
  }
  cout << "\n" << endl;
 }
 // the second
 return;
}
/*
  7. 读入一行文本,包含若干个单词(以空格间隔,%结尾)。将其中以 A 开头的
  单词与以 N 结尾的单词,用头尾交换的办法予以置换。
*/
//==============================================================================
// question7
//==============================================================================
void question7()
{//思路,两个指针,一个定位符合要求的位置,一个定位符合要求的结尾位置
 // do not read file, only use array
 char cstr[] = "fow Nao feo Ala fwoN ofw lox Nafow afoeN ";
 cout << cstr << "\n" << endl;
 char* wordstart = NULL;
 char* wordend = NULL;
 int k = 0;
 bool needchange = false;
 while ( cstr[k] != NULL )
 {
  if ( cstr[k] == ' ' )
  {
   k++;
   continue;
  }
  wordstart = &cstr[k];
  if ( cstr[k] == 'A' )
  {
   needchange = true;
  }
  while ( ( cstr[k] != ' ' ) && ( cstr[k] != NULL ) )
  {
   k++;
  }
  k--;//回退
  if ( cstr[k] == 'N' )
  {
   needchange = true;
  }
  if ( needchange )// 符合要求,按照要求转换数据
  {
   wordend = &cstr[k];
   char temp;
   while ( wordstart < wordend )
   {
    temp = *wordstart;
    *wordstart = *wordend;
    *wordend = temp;
    wordstart++;
    wordend--;
   }
  }
  needchange = false;
  k++;
  k++;
 }
 cout << cstr << "\n" << endl;
 return;
}
/*
 8. 输入两个正整数X,Y,将X,Y化为二进制数,然后将这两个二进制数作二进
  制加法运算,再将结果化为十进制数输出。
*/
//==============================================================================
// question8
//==============================================================================
int question8( int x, int y )
{
 // 几进制的加法转换成10进制的结果都是十进制加法的结果。
 if ( ( x <= 0 ) || ( y <= 0 ) )
 {
  cout << "bad input number, please input positive number" << endl;
  return -1;
 }
 unsigned int result = 0;//结果保证不越界
 return result = x + y;
}
/*
  9. 四人玩火柴棍游戏,每一次都是三个人赢,一个人输。输的人要按赢者手中的火柴
  数进行赔偿,即赢者手中有多少根火柴棍,输者就赔偿多少根。现知道玩过四次后,
  每人恰好输过一次, 而且每人手中都正好有16根火柴。问此四人做游戏前手中各有
  多少根火柴? 编程解决此问题。
*/
//==============================================================================
// question9
//==============================================================================
void question9()
{// 思路,倒推
 int sum = 0;
 int total = 64;
 int a[4] = { 16, 16, 16, 16 };
 for ( int i = 0; i < 4; i++ )//四次游戏,四个人每人一次
 {
  for ( int j = 0; j < 4; j++ )//四次重新赋值
  {
   if ( j == i )//输的不用重新赋值
   {
    continue;
   }
   a[j] /= 2;
   sum += a[j];
  }
  a[i] = total - sum;//输的人重新赋值
  sum = 0;
 }
 for ( int j = 0; j < 4; j++ )//输出
 {

  cout << a[j] << " ";
 }
 cout << endl;
 return;
}
/*
 10. 如图1所示,编写程序计算               ┎┰┰┰┰┰┰┰┰┰┒
    大大小小正方形共有多少?当最小          ┠╂╂╂╂╂╂╂╂╂┨
    正方行边长为1时,它们的总面积          ┠╂╂╂╂╂╂╂╂╂┨
    共为多少?                              ┠╂╂╂╂╂╂╂╂╂┨
                                            ┠╂╂╂╂╂╂╂╂╂┨
                                            ┠╂╂╂╂╂╂╂╂╂┨
                                            ┠╂╂╂╂╂╂╂╂╂┨
                                            ┠╂╂╂╂╂╂╂╂╂┨
                                            ┠╂╂╂╂╂╂╂╂╂┨
                                            ┠╂╂╂╂╂╂╂╂╂┨
                                            ┖┸┸┸┸┸┸┸┸┸┚
*/
//==============================================================================
// question10
//==============================================================================
void question10()
{//思路,方块的边长单位可以1,2,。。。。10
 int i, j;
 int area = 0;
 int len = 1;
 int sum = 0;
 const int N = 10;
 int a[N][N];//每个值都是一个方块,边长是1
 for ( i = 0; i < N; i++ )
 {
  for ( j = 0; j < N; j++ )
  {
   a[i][j] = 1;
  }
 }

 while ( len <= 10 )//边长最大为10
 {
  for ( i = 0; i <= 10 - len; i++ )//根据边长循环查找
  {
   for ( j = 0; j <= 10 - len; j++)
   {
    sum++;
   }
  }
  area += sum * ( len * a[0][0] * len * a[0][0] );
  len++;
 }
 cout << "number of squares: " << sum << "\n";
 cout << "area of those squares: " << area << endl;

 return;
}
/*
  11. 巧排数字。将1、2、...、20这20个数排成一排,使得相邻的两个数之
  和为一个素数,且首尾两数字之和也为一个素数。编程打印出所有的排法。
  符合条件的组合太多了 6309301个组合
*/
//==============================================================================
// question11
//==============================================================================
void question11()
{
//思路,对于任一排列,不论哪个数字排在第一位,都应算是一种排列,故将1锁定在第一位
 // 很笨的方法实现,符合要求的结果太多,上百万
 ofstream fout;
 fout.open("c:\\output.txt");
 int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s;
 for ( a = 2; a <= 20; a++ ) {
  if ( !( isPrimeNumber( a + 1 ) ) )//不是素数,不能继续
  {
   continue;
  }
  for ( b = 2; b <= 20; b++ ) {
   if ( !( isPrimeNumber( a + b ) ) )
   {
    continue;
   }
   for ( c = 2; c <= 20; c++ ) {
    if ( !( isPrimeNumber( b + c ) )
     || ( c == a ) )
    {//不是素数或者跟以前的数字重复不能继续
     continue;
    }
    for ( d = 2; d <= 20; d++ ) {
     if ( !( isPrimeNumber( c + d ) )
      || ( d == a )
      || ( d == b ) )
     {
      continue;
     }
     for ( e = 2; e <= 20; e++ ) {
      if ( !( isPrimeNumber( d + e ) )
       || ( e == a )
       || ( e == b )
       || ( e == c ) )
      {
       continue;
      }
      for ( f = 2; f <= 20; f++ ) {
       if ( !( isPrimeNumber( e + f ) )
        || ( f == a )
        || ( f == b )
        || ( f == c )
        || ( f == d ) )
       {
        continue;
       }
       for ( g = 2; g <= 20; g++ ) {
        if ( !( isPrimeNumber( f + g ) )
        || ( g == a )
        || ( g == b )
        || ( g == c )
        || ( g == d )
        || ( g == e ) )
        {
         continue;
        }
        for ( h = 2; h <= 20; h++ ) {
         if ( !( isPrimeNumber( g + h ) )
         || ( h == a )
         || ( h == b )
         || ( h == c )
         || ( h == d )
         || ( h == e )
         || ( h == f ) )
         {
          continue;
         }
         for ( i = 2; i <= 20; i++ ) {
          if ( !( isPrimeNumber( h + i ) )
          || ( i == a )
          || ( i == b )
          || ( i == c )
          || ( i == d )
          || ( i == e )
          || ( i == f )
          || ( i == g ) )
          {
           continue;
          }
          for ( j = 2; j <= 20; j++ ) {
           if ( !( isPrimeNumber( i + j ) )
           || ( j == a )
           || ( j == b )
           || ( j == c )
           || ( j == d )
           || ( j == e )
           || ( j == f )
           || ( j == g )
           || ( j == h ) )
           {
            continue;
           }
           for ( k = 2; k <= 20; k++ ) {
            if ( !( isPrimeNumber( j + k ) )
             || ( k == a )
             || ( k == b )
             || ( k == c )
             || ( k == d )
             || ( k == e )
             || ( k == f )
             || ( k == g )
             || ( k == h )
             || ( k == i ) )
            {
             continue;
            }
            for ( l = 2; l <= 20; l++ ) {
             if ( !( isPrimeNumber( k + l ) )
              || ( l == a )
              || ( l == b )
              || ( l == c )
              || ( l == d )
              || ( l == e )
              || ( l == f )
              || ( l == g )
              || ( l == h )
              || ( l == i )
              || ( l == j ) )
             {
              continue;
             }
             for ( m = 2; m <= 20; m++ ) {
              if ( !( isPrimeNumber( l + m ) )
               || ( m == a )
               || ( m == b )
               || ( m == c )
               || ( m == d )
               || ( m == e )
               || ( m == f )
               || ( m == g )
               || ( m == h )
               || ( m == i )
               || ( m == j )
               || ( m == k ) )
              {
               continue;
              }
              for ( n = 2; n <= 20; n++ ) {
               if ( !( isPrimeNumber( m + n ) )
                || ( n == a )
                || ( n == b )
                || ( n == c )
                || ( n == d )
                || ( n == e )
                || ( n == f )
                || ( n == g )
                || ( n == h )
                || ( n == i )
                || ( n == j )
                || ( n == k )
                || ( n == l ) )
               {
                continue;
               }
               for ( o = 2; o <= 20; o++ ) {
                if ( !( isPrimeNumber( n + o ) )
                 || ( o == a )
                 || ( o == b )
                 || ( o == c )
                 || ( o == d )
                 || ( o == e )
                 || ( o == f )
                 || ( o == g )
                 || ( o == h )
                 || ( o == i )
                 || ( o == j )
                 || ( o == k )
                 || ( o == l )
                 || ( o == m ) )
                {
                 continue;
                }
                for ( p = 2; p <= 20; p++ ) {
                 if ( !( isPrimeNumber( o + p ) )
                  || ( p == a )
                  || ( p == b )
                  || ( p == c )
                  || ( p == d )
                  || ( p == e )
                  || ( p == f )
                  || ( p == g )
                  || ( p == h )
                  || ( p == i )
                  || ( p == j )
                  || ( p == k )
                  || ( p == l )
                  || ( p == m )
                  || ( p == n ) )
                 {
                  continue;
                 }
                 for ( q = 2; q <= 20; q++ ) {
                  if ( !( isPrimeNumber( p + q ) )
                   || ( q == a )
                   || ( q == b )
                   || ( q == c )
                   || ( q == d )
                   || ( q == e )
                   || ( q == f )
                   || ( q == g )
                   || ( q == h )
                   || ( q == i )
                   || ( q == j )
                   || ( q == k )
                   || ( q == l )
                   || ( q == m )
                   || ( q == n )
                   || ( q == o ) )
                  {
                   continue;
                  }
                  for ( r = 2; r <= 20; r++ ) {
                   if ( !( isPrimeNumber( q + r ) )
                    || ( r == a )
                    || ( r == b )
                    || ( r == c )
                    || ( r == d )
                    || ( r == e )
                    || ( r == f )
                    || ( r == g )
                    || ( r == h )
                    || ( r == i )
                    || ( r == j )
                    || ( r == k )
                    || ( r == l )
                    || ( r == m )
                    || ( r == n )
                    || ( r == o )
                    || ( r == p ) )
                   {
                    continue;
                   }
                   for ( s = 2; s <= 20; s++ ) {
                    if ( !( isPrimeNumber( r + s ) )
                     || !( isPrimeNumber( s + 1 ) )
                     || ( s == a )
                     || ( s == b )
                     || ( s == c )
                     || ( s == d )
                     || ( s == e )
                     || ( s == f )
                     || ( s == g )
                     || ( s == h )
                     || ( s == i )
                     || ( s == j )
                     || ( s == k )
                     || ( s == l )
                     || ( s == m )
                     || ( s == n )
                     || ( s == o )
                     || ( s == p )
                     || ( s == q ) )
                    {
                     continue;
                    }
                    int z = 1;
                    fout << z << "  ";
                    fout << a << "  ";
                    fout << b << "  ";
                    fout << c << "  ";
                    fout << d << "  ";
                    fout << e << "  ";
                    fout << f << "  ";
                    fout << g << "  ";
                    fout << h << "  ";
                    fout << i << "  ";
                    fout << j << "  ";
                    fout << k << "  ";
                    fout << l << "  ";
                    fout << m << "  ";
                    fout << n << "  ";
                    fout << o << "  ";
                    fout << p << "  ";
                    fout << q << "  ";
                    fout << r << "  ";
                    fout << s << "  ";
                    fout << "\r\n";
                   }
                  }
                 }
                }
               }
              }
             }
            }
           }
          }
         }
        }
       }
      }
     }
    }
   }
  }
 }
 fout << flush;
 fout.close();
 return;
}
/*
 12. 下图是一个集装箱仓库,阴影部分表示有集装箱存放不能通过,无阴影处为临时通
 道。当有人要从入口处到达出口处时,必须寻找可通过路线,请你找出可完成这个过程
 的最方便(即用最短路线)到达出口处的路径。

          ┎┰┰┰入口┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┰┒
          ┠╂╂╂──╂╂╂╂┸┸╂┸┸╂┸┸╂┸┸╂╂╂╂┸┸╂╂╂┨
          ┠╂╂╂──╂┸┸╂──╂┰┰╂┰┰╂──╂╂╂╂──╂╂╂┨
          ┠╂╂╂──╂┰┰╂┰┰╂╂╂╂╂╂╂──╂┸┸╂──╂╂╂┨
          ┠╂╂╂──╂╂╂╂╂╂╂╂╂╂╂╂╂┰┰╂┰┰╂┰┰╂╂╂┨
          ┠╂╂╂──╂┸┸╂┸┸╂┸┸╂┸┸╂┸┸╂┸┸╂┸┸╂╂╂┨
          ┠╂╂╂──╂┰┰╂┰┰╂┰┰╂──╂┰┰╂──╂┰┰╂╂╂┨
          ┠╂╂╂──╂╂╂╂╂╂╂╂╂╂──╂╂╂╂──╂╂╂╂╂╂┨
          ┠╂╂╂──╂╂╂╂┸┸╂┸┸╂──╂╂╂╂──╂┸┸╂╂╂┨
          ┠╂╂╂──╂╂╂╂┰┰╂┰┰╂┰┰╂╂╂╂┰┰╂──╂╂╂┨
          ┖┸┸┸──┸┸┸┸┸┸┸┸┸┸┸┸┸┸┸┸┸┸┸出口┸┸┸┚
*/
//==============================================================================
// question12
//==============================================================================
void question12()
{
 const int N = 12;
 //1是墙,0是通道,给定迷宫外面包含一层墙体省得判断数组越界
 int maze[N][N] =  { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1 },
      { 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1 },
      { 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1 },
      { 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
      { 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1 },
      { 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1 },
      { 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 },
      { 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1 },
      { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
 int i(1), j(2);
 MazeData mazedata( -1, 0, i, j );//-1表示起始点,没有前一个方向
 MazeData endmazedata( 0, 0, 10, 9 );
 MyStack<MazeData> mazestack;
 while ( !( mazedata.m_X == endmazedata.m_X && mazedata.m_Y == endmazedata.m_Y ) )
 {
  switch( mazedata.m_Orient )
  {
  case 0://右下左上的搜索顺序
   {
    if ( mazedata.m_Orient == mazedata.m_PreOrient )
    {
     mazedata.m_Orient++;
// 下一个合格的点不能是上一个栈元素,进入下一个搜索方向
    }
    else
    {
     if ( maze[mazedata.m_X][mazedata.m_Y + 1] == 0 )
     {
      mazedata.m_Orient++;//下次不能再次搜索这个方向
      mazestack.Push( mazedata );
      mazedata.m_Orient = 0;
      mazedata.m_Y++;
      mazedata.m_PreOrient = 2;
      break;
// 下一个元素合格,就把当前点的压栈,然后用下一个合格的点进行查询
     }
     else
     {
      mazedata.m_Orient++;
// 如果这个方向上没有合格的点,则进入下一个方向
     }
    }
   }
  case 1:
   {
    if ( mazedata.m_Orient == mazedata.m_PreOrient )
    {
     mazedata.m_Orient++;
    }
    else
    {
     if ( maze[mazedata.m_X + 1][mazedata.m_Y] == 0 )
     {
      mazedata.m_Orient++;
      mazestack.Push( mazedata );
      mazedata.m_Orient = 0;
      mazedata.m_X++;
      mazedata.m_PreOrient = 3;
      break;
     }
     else
     {
      mazedata.m_Orient++;
     }
    }
   }
   case 2:
   {
    if ( mazedata.m_Orient == mazedata.m_PreOrient )
    {
     mazedata.m_Orient++;
    }
    else
    {
     if ( maze[mazedata.m_X][mazedata.m_Y - 1] == 0 )
     {
      mazedata.m_Orient++;
      mazestack.Push( mazedata );
      mazedata.m_Orient = 0;
      mazedata.m_Y--;
      mazedata.m_PreOrient = 0;
      break;
     }
     else
     {
      mazedata.m_Orient++;
     }
    }
   }
   case 3:
   {
    if ( mazedata.m_Orient == mazedata.m_PreOrient )
    {
     mazedata.m_Orient++;
    }
    else
    {
     if ( maze[mazedata.m_X - 1][mazedata.m_Y] == 0 )
     {
      mazedata.m_Orient++;
      mazestack.Push( mazedata );
      mazedata.m_Orient = 0;
      mazedata.m_X--;
      mazedata.m_PreOrient = 1;
      break;
     }
     else
     {
      mazedata.m_Orient++;
     }
    }
   }
   default:
    {
     if ( mazestack.StackCount() == 0 )
     {
      mazedata.m_Orient++;
      if ( mazedata.m_Orient > 3 )
      {
      //回到起始点,且无可行路线,无迷宫无解
      cout << " the maze data is wrong" << endl;
      return;
      }
     }
     else
     {
      // 回退到上一个点
      mazedata = mazestack.TopData();    
      mazestack.Pop( mazedata );
     }
     break;
    }
  }
 }
 // 最后一个合格点入栈
 mazestack.Push( endmazedata );
 //  重画迷宫
 for ( i = 0; i < N; i++ )
 {
  for ( j = 0; j < N; j++ )
  {
   maze[i][j] = 1;
  }
 }
 while ( mazestack.StackCount() )
 {
  // 迷宫中正确点集赋值
  mazedata = mazestack.TopData();
  maze[mazedata.m_X][mazedata.m_Y] = 0;
  mazestack.Pop( mazedata );
 }
 for ( i = 0; i < N; i++ )
 {
  for ( j = 0; j < N; j++ )
  {
   cout << maze[i][j] << "  ";
  }
  cout << "\n";
 }
 cout << endl;
 return;
}
/*
 13. 有N个硬币(N为偶数)正面朝上排成一排,每次将 N-1 个硬币翻过来放在原位
 置, 不断地重复上述过程,直到最后全部硬币翻成反面朝上为止。编程让计算机把
 翻币的最简过程及翻币次数打印出来(用*代表正面,O 代表反面)。

  0 0 0 0 0 0
  ——————
  0 1 1 1 1 1
  1 0 1 1 1 1
  1 1 0 1 1 1
  1 1 1 0 1 1
  1 1 1 1 0 1
  1 1 1 1 1 0
  ——————
证明:上次贴出来的证明是错误的,这次没错了
设总共翻了S次,零表示没有翻动,1表示翻动,故0的个数是S
设某列翻动的次数(1)为a,不翻动(0)的次数为b
如果想翻到另外一面,则a为奇数
如果S=2*k-1, k = 1,2,3,.....N,为奇数,而硬币数量为偶数,
则,必然至少有一列的b的次数为零,或者为偶数,因为b的总数
是奇数,因此其它列中必然有一列的0为奇数,因此,那一列a的次数
为奇数S-奇数个零,为偶数,因此无法翻到另一面。故S不能为奇数
如果s=2*k, k = 1,2,3,.....N,a+b为偶数,a需要为奇数,因此任意一列如果想翻
到另外一面,必须使b为奇数,1,3,.......
最少次数,故b=1
故结果如上,没有函数实现
*/
//==============================================================================
// question13
//==============================================================================
void question13()
{
 return;
}
/*
 14. 有黑白棋子各有N个(分别用*和O代替),按下图方式排列

        ***...***OOO...OOO

            N个黑棋            N个白棋

 允许将相邻两个棋子互换位置,最后使队形成黑白交替排列,试编程实现该操作。
*/
//==============================================================================
// question14
//==============================================================================
/*
 14. 有黑白棋子各有N个(分别用*和O代替),按下图方式排列

        ***...***OOO...OOO

            N个黑棋            N个白棋

 允许将相邻两个棋子互换位置,最后使队形成黑白交替排列,试编程实现该操作。
*/
void question14()
{
 const int N = 50;
 char array[2 * N];
 char temp;
 int i = 0;
 int j, k(1);
 for ( ; i < N; i++ )

 {
  array[i] = '*';
 }
 for ( i = N; i < 2 * N; i++ )
 {
  array[i] = 'O';
 }
 for ( i = N - 1; i > 0; i-- )//第i个黑棋
 {
  for ( j = i; j < 2 * ( N - k ); j++ )//该黑棋向后移动
  {
   temp = array[j];
   array[j] = array[j + 1];
   array[j + 1] = temp;
   for ( i = 0; i < 2 * N; i++ )//显示每次运动结果
   {
    cout << array[i];
   }
  }
  k++;
 }
 cout << endl;
 return;
}
/*
 17. 编写一个程序,当输入不超过60个字符组成的英文文字时,计算机将这个句子
 中的字母按英文字典字母顺序重新排列,排列后的单词的长度要与原始句子中的长度
 相同。例如:

    输入:

    THE PRICE OFBREAD IS ¥1 25 PER POUND

    输出:

    ABC DDEEE EFHIINO OP ¥1 25 PPR RRSTU

 并且要求只对A到Z的字母重新排列,其它字符保持原来的状态。
*/
//==============================================================================
// question17
//==============================================================================
void question17()
{
 int i, j;
 char strorg[61];
 cout << " please input string, length must less than 60 " << "\n" << endl;
 int len = 61;//最大输入长度, 字符串大于60部分被截断
 cin.getline( strorg, len );
 len = 0;
 for ( i = 0; i < sizeof( strorg ) / sizeof( char ); i++ )
 {
  if ( strorg[i] == NULL)
  {
   break;
  }
  len++;//求得实际输入长度
 }
 char* pcursor = strorg;//这个指针将指向符合要求的字符
 char temp;
 for ( i = 0; i < len - 1; i++ )
 {
  if ( *pcursor > 'Z' || *pcursor < 'A' )
  {
   pcursor++;//非A~Z字母略过
   continue;
  }
  for ( j = i + 1; j < len - i; j++ )
  {
   if ( *( pcursor + j ) > 'Z' || *( pcursor + j )  < 'A' )
   {
    continue;//非A~Z字母略过
   }
   if ( *( pcursor + j ) < * pcursor )
   {//满足条件的字母交换
    temp = *pcursor;
    *pcursor = *( pcursor + j ) ;
    *( pcursor + j )  = temp;
   }
  }
  pcursor++;
 }

 for ( i = 0; i < len; i++ )
 {
  cout << strorg[i];
 }
 cout << "\n" << endl;
}

/*
19. (背包问题) 有 N 件物品 d1,......dN,每件物品重量为 W1,..., WN
(Wi > 0), 每件物品价值为 V1,......VN (Vi>0)。用这N件物品的某个子集
填空背包,使得所取物品的总重量<=TOTAL,并设法使得背包中物品的价值尽可
 能高。
           重量千克 等级                 重量千克   等级   700千克总重
 云层模型    36      5          太阳黑子   92        2
 光速        264     9          肿瘤       65        8
 太阳能      188     6          失重蔓藤   25        3
 双子星      203     8          太空尘埃   170       6
 相对论      104     8          宇宙射线   80        7
 种子成活率  7       6          酵母发酵   22        4
*/
void question19()
{//思路:n个元素的子集有2^n个,因此用000001110101来表示某个子集
//1表示子集中有某个元素,0表示没有,每一位对应一个元素
 const int limitwight = 700;
 const int N = 12;
 int weight[N] = { 36, 264, 188, 203, 104, 7, 92, 65, 25, 170, 80, 22 };
 int bestset[N];
 int power[N] = { 5, 9, 6, 8, 8, 6, 2, 8, 3, 6, 7, 4 };
 int i(0), j(0);
 int subset[N + 1];//最后一位将用于判断是否测试完所有子集
 for ( i  = 0; i <= N; i++ )
 {
  subset[i] = 0;
 }
 int maxvalue = 0;
 int tempwight = 0;
 int tempvalue = 0;
 while ( 1 )
 {
  j = 0;//重置起始值
  tempvalue = 0;
  tempwight = 0;
  while( 1 )
  {
   subset[j]++;
   if ( subset[j] > 1 )
   {
    subset[j] = 0;
    j++;
   }
   else
   {
    break;
   }//这个while将从子集000000000000开始不断加1,将这个数组看成二进制的表示方法
  }
  if ( subset[N] == 1 )当子集111111111111加1之后表示二进制数组的最高位为1,所有子集计算完毕
  {
   break;
  }
  for ( i = 0; i < N; i++ )
  {
   tempwight += subset[i] * weight[i];//每一个集合的总重量
   tempvalue += subset[i] * power[i];//每一个集合的总价值
  }
  if ( ( tempwight < limitwight ) && ( tempvalue > maxvalue ) )
  {
   for ( i = 0; i < N; i++ )
   {
    bestset[i] = subset[i];
   }
   maxvalue = tempvalue;//如果合格就重新记录价值最高的集合
  }
 }
 for ( i = 0; i < N; i++ )//输出,可以用switch来输出试验的名称,输出效果更好,不做了
 {
  cout << bestset[i] << " ";
 }
 cout << "\n" << "the max value is " << maxvalue << "\n" << endl;
}

 

 

 /************************************************************************/
/* this class is the array templete                                     */
/************************************************************************/
template< typename T>
class MyArray
{
public:
 MyArray();
 ~MyArray();
 int Count() const;
 T& operator[]( int index );
 void Append( T& object );
 void Insert( T& object, int pos );
 void Delete( int index );
 bool Find( T& object, int& index );
 void CleanArray();
private:
 struct arrayqueue
 {
  T m_Data;
  arrayqueue* m_Next;
 };
private:
 int m_Count;
 arrayqueue* m_Header;
 arrayqueue* m_Last;
};
// functions implement
template< typename T>
MyArray<T>::MyArray() : m_Count(0), m_Header(NULL), m_Last(NULL)
{
}

template< typename T>
MyArray<T>::~MyArray()
{
 m_Last = m_Header;
 while ( m_Last != NULL )
 {
  m_Header = m_Header->m_Next;
  delete m_Last;
  m_Last = m_Header;
 }
}

template< typename T>
int MyArray<T>::Count() const
{
 return m_Count;
}

template< typename T>
void MyArray<T>::Append( T& object )
{
 if ( m_Header == NULL )
 {
  arrayqueue* temp = new arrayqueue;
  temp->m_Data = object;
  temp->m_Next = NULL;
  m_Header = temp;
  m_Last = m_Header;
  m_Count++;
 }
 else
 {
  arrayqueue* temp = new arrayqueue;
  temp->m_Data = object;
  temp->m_Next = NULL;
  m_Last->m_Next = temp;
  m_Last = temp;
  m_Count++;
 }
}
template< typename T>
T& MyArray<T>::operator[]( int index )
{
 if ( index >= m_Count || index < 0 )
 {
  exit( -1 );
 }
 else
 {
  arrayqueue* temp = m_Header;
  while ( index )
  {
   temp = temp->m_Next;
   index--;
  }
  return temp->m_Data;
 }
}
template< typename T>
void MyArray<T>::Insert( T& object, int pos )
{
 if ( pos < 0 )
 {
  return;
 }
 if ( pos >= m_Count )//add to the last position
 {
  arrayqueue* temp = new arrayqueue;
  temp->m_Data = object;
  temp->m_Next = NULL;
  m_Last->m_Next = temp;
  m_Last = temp;
 }
 else
 {
  arrayqueue* newtemp = new arrayqueue;
  newtemp->m_Data = object;
  newtemp->m_Next = NULL;
  if ( pos == 0 )
  {
   newtemp->m_Next = m_Header->m_Next;
   m_Header = newtemp;
  }
  else
  {
   arrayqueue* temp = m_Header;
   pos--;
   while ( pos )
   {
    temp = temp->m_Next;
    pos--;
   }
   newtemp->m_Next = temp->m_Next;
   temp->m_Next = newtemp;
  }
 }
 m_Count++;
 return;
}
template< typename T>
void MyArray<T>::Delete( int index )
{
 if ( index < 0 || index >= m_Count )
 {
  return;//prompt user maybe better
 }
 else
 {
  arrayqueue* temp = m_Header;
  if ( index == 0 )
  {
   if ( m_Count == 1 )
   {
    m_Last = NULL;
    m_Header = NULL;
    delete temp;
   }
   else
   {
    m_Header = m_Header->m_Next;
    delete temp;
   }
  }
  else
  {
   bool lastneedchange = false;
   if ( index == m_Count - 1 )
   {
    lastneedchange = true;
   }
   index--;
   while ( index )
   {
    temp = temp->m_Next;
    index--;
   }
   if ( lastneedchange )
   {
    delete temp->m_Next;
    m_Last = temp;
   }
   else
   {
    arrayqueue* deltemp = temp->m_Next;
    temp->m_Next = temp->m_Next->m_Next;
    delete deltemp;
   }
   
  }
 }
 m_Count--;
 return;
}

template< typename T>
bool MyArray<T>::Find( T& object, int& index )
{
 arrayqueue* temp = m_Header;
 for ( int i = 0; i < m_Count; i++ )
 {
  if ( temp->m_Data == object )
  {
   index = i;
   return true;
  }
 }
 return false;
}

template< typename T>
void MyArray<T>::CleanArray()
{
 m_Last = m_Header;
 while ( m_Last != NULL )
 {
  m_Header = m_Header->m_Next;
  delete m_Last;
  m_Last = m_Header;
 }
 m_Count = 0;
}


/************************************************************************/
/* the follow code for N queen question                                 */
/************************************************************************/
struct queenpos
{
 int xpos;
 int ypos;
 queenpos& operator=( queenpos& object )
 {
  if ( this != &object )
  {
   this->xpos = object.xpos;
  this->ypos = object.ypos;
  }
  return *this;
 }
 bool operator==( queenpos& object )
 {
  if ( this->xpos == object.xpos && this->ypos == object.ypos )
  {
   return true;
  }
  return false;
 }
};

/*
 20. (N皇后) 在国际象棋的棋盘上放置N个皇后,使其不能互相攻击,即任意
 两个皇后不能处在棋盘的同一行,同一列,同一斜线上,试问共有多少种摆法?
*/
//==============================================================================
// question20
//==============================================================================
void question20()
{
 int i(0), j(0), k(0);
 const int N = 16;//可以任意设置
 char a[N][N];
 MyArray<queenpos> queenArray;//放置正确的王后位置
 queenpos pos;//起始王后的位置
 pos.xpos = 0;
 pos.ypos = 0;
 bool conflict = false;//是否跟前面摆放的王后冲突标志
 for ( ; ; )
 {
  for ( j = 0; j < queenArray.Count(); j++ )//这个for循环用于判断是否跟前面的王后冲突
  {
   if ( pos.ypos == queenArray[j].ypos )
   {
    conflict = true;
    break;
   }
   else if ( abs( pos.ypos - queenArray[j].ypos ) == abs( pos.xpos - queenArray[j].xpos ) )
   {//45度或135度
    conflict = true;
    break;
   }
  }
  if ( conflict )//如果冲突,那么这个王后应该换个位置
  {
   pos.ypos++;//换位置
   while ( pos.ypos >= N )//如果当前行的位置都不满足要求,需要退出当前行,回退到上一行
   {
    if ( queenArray.Count() == 0 )//如果是第一行所有位置都遍历了,退出
    {
     return;
    }
    pos = queenArray[queenArray.Count() - 1];//王后位置应该回退,并且移位
    pos.ypos++;
    queenArray.Delete( queenArray.Count() - 1 );//删除不符合要求的王后位置
   }
  }
  else
  {
   queenArray.Append( pos );//位置正确,就将位置加入数组
   pos.xpos++;//新的王后位置在下一行,从首位置遍历
   pos.ypos = 0;
  }
  if ( queenArray.Count() == N )//如果N个王后的正确位置都求出,则显示
  {
   for ( k = 0; k < N; k++ )
   {//初始化数组
    for ( j = 0; j < N; j++ )
    {
     a[k][j] = '*';
    }
   }
   for ( k = 0; k < N; k++ )
   {//放置王后
    a[queenArray[k].xpos][queenArray[k].ypos] = 'Q';
   }
   for ( k = 0; k < N; k++ )
   {//显示
    for ( j = 0; j < N; j++ )
    {
     cout << a[k][j] << ' ';
    }
    cout << "\n";
   }
   cout << endl;
   pos = queenArray[0];//得到刚才的结果的第一个王后的位置,并向后移一位,重新遍历
   pos.ypos++;
   if ( pos.ypos >= N )//如果是第一行所有位置都遍历了,退出
   {
    return;
   }
   queenArray.CleanArray();//清空数组
  }
  conflict = false;
 }
}

 

/*
22. 在一个4*4的小方格(如图所示)中放置8个*号,使得每行每列放且
仅放两个*号。

  ┌─┬─┬─┬─┐
  │*│*│  │  │
  ├─┼─┼─┼─┤
  │*│  │*│  │
  ├─┼─┼─┼─┤
  │  │*│  │*│
  ├─┼─┼─┼─┤
  │  │  │*│*│
  └─┴─┴─┴─┘
 
 求出所有的基本解。
*/
void question22()
{//思路:对于任意一行,两个*号的分布有若干种情况,这些结果可以视为一个集合
 //每一行的集合是相等的,对N个集合进行排列,遇到合适的子集组合,就打印
 const int N = 4;//任意设置,当n为7的时候,结果有
 int i(0), j(0), k(0);
 int result = 0;
 bool isOk = true;
 int display[N][N] = { 0 };//用于显示
 MyArray<ArrayPoint> pointSet;//存放集合元素,合适的两个点,放在一起
 ArrayPoint point;
 int cursorArray[N] = { 0 };//用于记录当前用哪个点组合,用于遍历
 for ( ; i < N - 1; i++ )//每一行的集合都是相等的,只求一个
 {
  for ( j = i + 1; j < N; j++ )
  {
   point.iY = i;//只需要加入列的位置即可
   pointSet.Append( point );
   point.iY = j;
   pointSet.Append( point );//两个点放在一起,最好定义一个结构体,懒了。
  }
 }
 while ( 1 )
 {
  for ( i = 0; i < N; i++ )//初始化显示数组
  {
   for ( j = 0; j < N; j++ )
   {
    display[i][j] = 0;
   }
  }
  for ( i = 0; i < N; i++ )//赋值
  {
   display[i][pointSet[cursorArray[i]].iY] = 1;
   display[i][pointSet[cursorArray[i] + 1].iY] = 1;
  }
  isOk = true;
  for ( i = 0; i < N; i++ )//判断是否合格
  {
   k = 0;
   for ( j = 0; j < N; j++ )
   {
    k += display[j][i];//一列相加
   }
   if ( k != 2 )
   {
    isOk = false;
    break;
   }
  }
  if ( isOk )//合格组合显示
  {
   cout << "result " << result << "\n";
   result++;
   for ( i = 0; i < N; i++ )
   {
    for ( j = 0; j < N; j++ )
    {
     cout << display[i][j] << ' ';
    }
    cout << "\n";
   }
   cout << "\n" << endl;
   // system( "pause" );
  }
  cursorArray[N - 1] += 2;//取下一个最下面一行的点组合(两个点)
  k = 0;
  while ( cursorArray[N - 1 - k] >= pointSet.Count() )
  {//如果遍历了最后一个,那么上一行的点组合要取下一个组合
   cursorArray[N - 1 - k] = 0;//上面一行取下一个组合,所有下面的行都要重新遍历
   k++;
   cursorArray[N - 1 - k] += 2;
   if ( ( k == N - 1 ) && ( cursorArray[N - 1 - k] >= pointSet.Count() ) )
   {
    return;//第一行的所有点组合都已经遍历,退出
   }
  }
 }

 return;
}


/*
24. 某地街道把城市分割成矩形方格,每一方格叫作块,某人从家中出发上班,
向东要走M块,向北要走N块,(见图)。请设计一个程序,由计算机寻找并
打印出所有的上班的路径。

  单位
 ┬   ┌─┬─┬─┬─┬─┬─┬─┐
 │   │  │  │  │  │  │  │  │
 │   ├─┼─┼─┼─┼─┼─┼─┤
 ↓   │  │  │  │  │  │  │  │
 M    ├─┼─┼─┼─┼─┼─┼─┤
 ↑   │  │  │  │  │  │  │  │
 │   ├─┼─┼─┼─┼─┼─┼─┤
 │   │  │  │  │  │  │  │  │
 ┴   └─┴─┴─┴─┴─┴─┴─┘
 家   ├─────→N ←─────┤
 ┬   ┌─┬─┬─┬─┬─┬─┬─┐
 │   │* │* │* │* │* │* │* │
 │   ├─┼─┼─┼─┼─┼─┼─┤
 ↓   │* │  │  │  │  │  │  │
 M    ├─┼─┼─┼─┼─┼─┼─┤
 ↑   │* │  │  │  │  │  │  │
 │   ├─┼─┼─┼─┼─┼─┼─┤
 │   │* │  │  │  │  │  │  │
 ┴   └─┴─┴─┴─┴─┴─┴─┘
 家   ├─────→N ←─────┤
 ┬   ┌─┬─┬─┬─┬─┬─┬─┐
 │   │  │* │* │* │* │* │* │
 │   ├─┼─┼─┼─┼─┼─┼─┤
 ↓   │* │* │  │  │  │  │  │
 M    ├─┼─┼─┼─┼─┼─┼─┤
 ↑   │* │  │  │  │  │  │  │
 │   ├─┼─┼─┼─┼─┼─┼─┤
 │   │* │  │  │  │  │  │  │
 ┴   └─┴─┴─┴─┴─┴─┴─┘
 ┬   ┌─┬─┬─┬─┬─┬─┬─┐
 │   │  │  │  │  │  │* │* │
 │   ├─┼─┼─┼─┼─┼─┼─┤
 ↓   │  │  │  │  │* │* │  │
 M    ├─┼─┼─┼─┼─┼─┼─┤
 ↑   │  │  │* │* │* │  │  │
 │   ├─┼─┼─┼─┼─┼─┼─┤
 │   │* │* │* │  │  │  │  │
 ┴   └─┴─┴─┴─┴─┴─┴─┘
 家   ├─────→N ←─────┤
*/
void question24()
{
 //思路:从上面的图可知,每一行都有一个路线的终点,上面一行的起始点
    //的纵坐标是该行的终点纵坐标,因此只需要将每一行的终点坐标记录即可
 //每行的终点纵坐标不能比下一行的终点纵坐标小
 int i(0), j(0), k(0);
 const int M = 4;// 可以任意设置
 const int N = 7;
 char a[M][N];// 用于显示路线
 RoadPoint point;// 记录每一行的终点
 point.iY = 0;
 MyStack<RoadPoint> roadstack;// 栈,用于遍历
 MyArray<RoadPoint> roadarray;// 用于显示,跟栈的内容一致
 for ( i = M - 1; i >= 0; i-- )
 {// 第一条路线的每一行的终点
  point.iX = i;
  roadstack.Push( point );
  roadarray.Append( point );//从最下面画起,数组第一个元素是最下面的点
 }//如果记录第一行的终点,就需要不断判断,所以第一行记录起始点
 while ( 1 )
 {

  // 开始绘画,初始化路线数组
  for ( i = 0; i < M; i++ )
  {
   for ( j = 0; j < N; j++ )
   {
    a[i][j] = ' ';
   }
  }
  j = 0;// 从最下面画起,j起始值为零
  for ( i = M - 1; i >= 0; i-- )
  {
   for ( ; j <= roadarray[M - 1 - i].iY; j++ )
   {
    a[i][j] = '*';
   }
   j = roadarray[M - 1 - i].iY;
   // 每行的起始点都是下一行的终点
  }
  for ( j = roadarray[roadarray.Count() - 1].iY; j < N; j++ )
  {
   a[0][j] = '*';// 最上面的一行画至终点
  }
  cout << "result " << k << "\n";// 第k个路线
  k++;
  for ( i = 0; i < M; i++ )// 绘画
  {
   for ( j = 0; j < N; j++ )
   {
    cout << a[i][j];
   }
   cout << "\n";
  }
  cout << "\n" << endl;

  // 重新赋值
  roadstack.Pop( point );// 弹出最上面两行
  roadstack.Pop( point );// 第一行起始点由第二行终点决定
  roadarray.Delete( roadarray.Count() - 1 );
  roadarray.Delete( roadarray.Count() - 1 );
  point.iY++;// 第二行终点向右移
  while ( point.iY >= N )// 达到边界值,下面一行需要移位
  {
   if ( roadstack.StackCount() == 0 )
   {
    break;// 栈空,需要退出
   }
   roadstack.Pop( point );
   roadarray.Delete( roadarray.Count() - 1 );
   point.iY++;
  }
  if ( roadstack.StackCount() == 0 && point.iY >= N )
  {
   break;// 栈空,并且最后一行的最后一个点也画完了,退出
  }
  while ( roadstack.StackCount() < M )
  {
   roadstack.Push( point );// 重新将终点压栈
   roadarray.Append( point );
   point.iX--;
  }
 }
}

 

 /*
 25. (量水) 用存水为M,N升的两个罐子,量出A升水。
*/
//==============================================================================
// question25
//==============================================================================
void question25()
{//思路,通过不断的向另一个桶到水,最终会倒出这个差值
 int M, N, A;
 cout << "please input the cubage of the big jar";
 cin >> M;
 cout << "please input the cubage of the little jar";
 cin >> N;
 cout << "please input the left cubage you want, must small than the big ont";
 cin >> A;
 if ( A > M || M <= N )
 {
  cout << "input data is wrong" << endl;
  return;
 }
 int i(0), j(0);// i present the big jar
 while (1)
 {
  if ( i == 0 )// i空,到满
  {
   i = M;
   cout << i << "  " << j << "\n";
   continue;
  }
  else if ( j == N ) // j满,到空
  {
   j = 0;
   cout << i << "  " << j << "\n";
   continue;
  }
  else
  {
   if ( i > N - j )
   {
    i = i - ( N - j );
    j = N;
    cout << i << "  " << j << "\n";
    if ( i == A )
    {
     break;
    }
    continue;
   }
   else
   {
    j += i;
    i = 0;    
    cout << i << "  " << j << "\n";
   }
  }
 }
 cout << endl;
}



/*
28. n枚银币 C1,C2,...,Cn, 其中有一块不合格,不合格的银币比正常的要重。现用
 一天平找出不合格的一块,要求在最坏的情况下,用的天平次数最少。
*/
void question28()
{
 const int N = 10;
 int times = 0;
 int leftweight(0);
 int rightweight(0);
 int a[N] = { 1, 1, 1, 1, 1, 2, 1, 1, 1, 1 };
 int i(0), j(0);
 int leftpos(1), rightpos(N);
 while ( 1 )
 {
  for ( i = leftpos - 1; i < leftpos + ( rightpos - leftpos + 1 ) / 2 - 1; i++ )
  {
   leftweight += a[i];
  }
  for ( j = leftpos + ( rightpos - leftpos + 1 ) / 2 - 1; j < leftpos + ( rightpos - leftpos + 1 ) / 2 * 2 - 1; j++ )
  {//leftpos + ( rightpos - leftpos + 1 ) / 2 * 2一定是这样写,前面是长度,然后乘以2
   rightweight += a[j];
  }
  if ( leftweight < rightweight )
  {
   leftpos += ( rightpos - leftpos + 1 ) / 2;
  }
  else if ( leftweight > rightweight )
  {//就像前面一样,有个奇数偶数的问题
   rightpos = leftpos + ( rightpos - leftpos + 1 ) / 2 - 1;
  }
  else
  {//当距离差为奇数的时候,会出现最后一个为假币的情况。
   times++;
   break;
  }
  times++;
  leftweight = 0;
  rightweight = 0;
  if ( ( rightpos - leftpos ) == 1 )
  {
   times++;
   break;
  }
 }
 cout << times << "\n" << endl;
 return;
}


/*
 36. 猴子选大王:
   ① N 只猴子站成一行,每隔 M 只从头到尾报数,反复进行,报过数的退出,打
 印每次退出的猴子的编号,直到剩下一只为止。
   ② N 只猴子站成一行,每 M 只报数。先从头到尾,报到尾后,再返回从尾到头
 报数,打印每次方向及过程,直到剩下二只时,以排到后面的(指报数方向)为大王。
   ③ N 只猴子围成一圈,从第 P 个开始,每隔 M 只报数,打印每次过程,只剩下
 一个时为大王。
*/
void question36()
{
 int i, j;
 const int N = 40;//you can modify it
 const int M = 3;
 struct MonkeyLink
 {
 public:
  int num;
  MonkeyLink* next;
 };
 // construct circle link
 MonkeyLink* header = new MonkeyLink;
 header->num = 1;
 header->next = NULL;
 MonkeyLink* tempheader = header;
 for ( i = 1; i < N; i++ )
 {
  MonkeyLink* temp = new MonkeyLink;
  temp->num = i + 1;
  temp->next = NULL;
  tempheader->next = temp;
  tempheader = temp;
 }
 tempheader->next = header;
 tempheader = header;
 // 1
 while ( tempheader != tempheader->next )
 {
  for ( j = 1; j < M - 1; j++)
  {
   tempheader = tempheader->next;
  }
  header = tempheader->next;
  cout << header->num << "  ";
  tempheader->next = header->next;
  delete header;
 }
 cout << tempheader->num << "\n" << endl;
 delete tempheader;
 // 2
 header = new MonkeyLink;
 header->num = 1;
 header->next = NULL;
 tempheader = header;
 for ( i = 1; i < N; i++ )
 {
  MonkeyLink* temp = new MonkeyLink;
  temp->num = i + 1;
  temp->next = NULL;
  tempheader->next = temp;
  tempheader = temp;
 }
 tempheader->next = header;
 tempheader = header;
 while ( tempheader != tempheader->next->next )
 {
  for ( j = 1; j < M * M - 1; j++)
  {
   tempheader = tempheader->next;
  }
  header = tempheader->next;
  cout << header->num << "  ";
  tempheader->next = header->next;
  delete header;
 }
 cout << "the last two is " << tempheader->num << " " << tempheader->next->num;
 cout << " and the king is " << "\n";
 if ( tempheader->num > tempheader->next->num )
 {
  cout << tempheader->num;
 }
 else
 {
  cout << tempheader->next->num;
 }
 cout << "\n" << endl;
 delete tempheader->next;
 delete tempheader;
 // 3
 const int P = 12;
 header = new MonkeyLink;
 header->num = 1;
 header->next = NULL;
 tempheader = header;
 for ( i = 1; i < N; i++ )
 {
  MonkeyLink* temp = new MonkeyLink;
  temp->num = i + 1;
  temp->next = NULL;
  tempheader->next = temp;
  tempheader = temp;
 }
 tempheader->next = header;
 tempheader = header;
 for ( j = 1; j < P; j++ )
 {
  tempheader = tempheader->next;
 }
 while ( tempheader != tempheader->next )
 {
  for ( j = 1; j < M - 1; j++)
  {
   tempheader = tempheader->next;
  }
  header = tempheader->next;
  cout << header->num << "  ";
  tempheader->next = header->next;
  delete header;
 }
 cout << "the king is " << tempheader->num << "\n" << endl;
 delete tempheader;

 return;
}

 


/*
 41. (合并链表) 已知两个链表 AN={a1,a2,...an}, BN={b1,b2,...bm}, 将其合并
 为一个链表 CN={a1,b1,a2,b2,...}
*/

/************************************************************************
   AHeader----->temp接受了Ax,AHeader就指向下一个位置
CHeader---->A1 A2 A3......................AN
  temp--->根据一个符号,变换指向A或B,当任意一个header为空时,指向另一个link就over
   B1 B2 B3......................BN
   BHeader----->temp接受了Bx,BHeader就指向下一个位置
CHeader位置不能动
*************************************************************************/
void question41()
{
 struct Link
 {
  int num;
  Link* next;
 };
 int i;
 int num = 1;
 Link* AHeader= NULL;
 Link* BHeader= NULL;
 Link* CHeader= NULL;
 Link* temp= NULL;
 const int M = 10;
 const int N = 15;//可以修改这两个link长度数据
 
 for ( i = 0; i < M; i++ )//构建A链表
 {
  if ( i == 0 )
  {
   AHeader = new Link;
   AHeader->num = num;
   BHeader = AHeader;//临时借用
   num += 2;
  }
  else
  {
   temp = new Link;
   temp->num = num;
   temp->next = NULL;
   BHeader->next = temp;
   num += 2;
   BHeader = BHeader->next;
  }
 }

 temp = AHeader;//显示Link
 for ( i = 0; i < M; i++ )
 {
  cout << temp->num << " ";
  temp = temp->next;
 }
 cout << "\n";
 for ( i = 0; i < N; i++ )//构建B链表
 {
  if ( i == 0 )
  {
   num = 2;//重置数据
   BHeader = NULL;//重置数据
   BHeader = new Link;
   BHeader->num = num;
   CHeader = BHeader;//临时借用
   num += 2;
  }
  else
  {
   temp = new Link;
   temp->num = num;
   temp->next = NULL;
   CHeader->next = temp;
   num += 2;
   CHeader = CHeader->next;
  }
 }

 temp = BHeader;//显示Link
 for ( i = 0; i < N; i++ )
 {
  cout << temp->num << " ";
  temp = temp->next;
 }
 cout << "\n";
 
 CHeader = AHeader;//指向首位置
 temp = CHeader;
 AHeader = AHeader->next;
 num = 0;//指示符

 while (1)
 {
  if ( num == 0 )//为0的时候,合并B链表的一个元素
  {
   temp->next = BHeader;
   temp = temp->next;
   BHeader = BHeader->next;
   if ( BHeader == NULL )
   {
    temp->next = AHeader;
    break;
   }
   num++;
  }
  else//为1的时候,合并A链表的一个元素
  {
   temp->next = AHeader;
   temp = temp->next;
   AHeader = AHeader->next;
   if ( AHeader == NULL )
   {
    temp->next = BHeader;
    break;
   }
   num--;
  }
 }
 //显示合并后的链表
 temp = CHeader;
 for ( i = 0; i < M + N; i++ )
 {
  cout << temp->num << " ";
  temp = temp->next;
 }
 cout << "\n" << endl;
 //销毁链表
 while ( CHeader != NULL )
 {
  temp = CHeader;
  CHeader = CHeader->next;
  delete temp;
 }
}

 


/*
 58. 将7万元投资到A,B,C三项目上,其利润见下表:
        投资额(万元)│ 1    2    3    4    5    6    7
        ──────┼────────────────────
            项  A  │0.11  0.13  0.15  0.24  0.24  0.30  0.35
                B  │0.12  0.16  0.21  0.25  0.25  0.29  0.34
            目  C  │0.08  0.12  0.20  0.26  0.26  0.30  0.35
  如何分配投资额,使获得的利润最大。
*/
void question58()
{
 const int N = 7;
 int i, j;
 double sum;
 double maxprofit(0.0);
 double A[N + 1] = { 0.0, 0.11, 0.13, 0.15, 0.24, 0.24, 0.30, 0.35 };
 double B[N + 1] = { 0.0, 0.12, 0.16, 0.21, 0.25, 0.25, 0.29, 0.34 };
 double C[N + 1] = { 0.0, 0.08, 0.12, 0.20, 0.26, 0.26, 0.30, 0.35 };
 int item[] = { 0, 0, 0 };
 for ( i = 0; i <= N; i++ )
 {
  for ( j = 0; j <= N; j++ )
  {
   if ( i + j > N)
   {
    continue;
   }
   sum = i * A[i] + j * B[j] + ( N - i - j ) * C[N - i - j];
   if ( sum > maxprofit )
   {
    maxprofit = sum;
    item[0] = i;
    item[1] = j;
    item[2] = N - i - j;
   }
  }
 }
 cout << " the max profit is " << maxprofit << " " << item[0];
 cout << item[1] << item[2] << "\n" << endl;

}


 /*
76. (省刻度尺问题)给定长度为 L 的直尺, L 为整数, 且L≤40. 为了能一次直接
量出  1,2,...,L 的各种长度, 该尺内部至少要有多少条刻度 ?  请输出最少刻度
数( 不含两端点)及每个刻度的位置. 测量长度时可利用两端点, 其位置分别为 0,
L.
输入: 由键盘输入 L.
输出: 用文本文件按以下格式输出结果(文件名: ANS2.TXT):
第 1 行: S ( 最少刻度数 )
第 2 行: 尺内 S 个刻度的位置
第 3 行至第 L+2 行: 每行输出 3 个用空格隔开的整数 t m n, 其中
1≤t≤L 为要测量的各长度, m,n 依次为该长度的起止刻度 (m<n).
例: 如果 L=6, 则一个正确的输出是:
2
1 4                    提示:  (1) 最少刻度数 S 应满足:
1 0 1                     C[S+2,2]=(S+2)*(S+1)/2≥L.
2 4 6                         (2) 除两端点外, 第一个刻度可取为
3 1 4                     A[1]=1, 第二个刻度可在 1, L-2, L-1 这
4 0 4                     三个数中选取.
5 1 6
6 0 6
*/
void question76()
{
//目前还没有尚未想出一种数学方法来证明自己的方法是否满足使用刻度最少
//思路:为了测量不同的刻度,那么每刻上一条刻度线,至少可以测量x,和
//L-x,跟以前的刻度相减,又可以得到其它刻度,那么这些刻度用一个数组
//表示,0表示还没有这个刻度尺寸,1表示有,那么这个数组没有了0元素,
//就表示所有刻度尺寸都有了。从0的位置开始刻上刻度长1,计算数组是否
//含有0元素,有则从L一端刻上刻度长度2,再次核查,是否缺少长度3,然后
//从0一边的最后一个刻度起始刻上刻度长3,类推,刻度总数至少要小于L/2
//当左边界刻度比右边界刻度大时,直接使用0, X计算
 int L;//尺子的长度
 while ( 1 )
 {
  cout << "input right ruler length" << "\n";
  cin >> L;
  if ( L >= 3 )
  {
   break;
  }
 }
 int i(0), k(0);
 int* lenarray = new int[L];//长度的数组,表示各个长度,
 //某位置为0表示还没有这个长度,1表示有这个长度
 for ( ; i < L; i++ )
 {
  *(lenarray + i) = 0;
 }
 *(lenarray + L - 1) = 1;//最长的测量不需要计算只需输出
 MyArray<int> lineposarray;//刻度线的位置
 lineposarray.Append(k);
 k = L;
 lineposarray.Append(k);//ruler两边的刻度位置
 //每次新的刻度都需要计算和这些已刻上的刻度的差
 RulerScale scaleinfo;
 scaleinfo.iLeftpos = 0;
 scaleinfo.iRightpos = L;//最后一个长度不需计算
 MyArray<RulerScale> scalearray;//用于保持上面的打印信息
 for ( i = 1; i <= L; i++ )
 {
  scaleinfo.iLen = i;
  scalearray.Append( scaleinfo );
 }
 int leftpos(0), rightpos(L);//刻新刻度的起始位置
 int len(1);//需要刻的第一个长度值
 bool needcontinue = true;
 k = 0;
 while ( needcontinue )
 {
  k++;
  if ( ( k % 2 ) != 0 )
  {
   leftpos += len;
   if ( leftpos > rightpos )
   {
    *(lenarray + len - 1) = 1;
    lineposarray.Append( len );
    scalearray[len - 1].iRightpos = len;
    scalearray[len - 1].iLeftpos = 0;
   }
   else
   {
    for ( i = 0; i < lineposarray.Count(); i++ )
    {
     if ( *(lenarray + abs( leftpos - lineposarray[i] ) - 1) == 0 )
     {
      *(lenarray + abs( leftpos - lineposarray[i] ) - 1) = 1;
      if ( leftpos > lineposarray[i] )
      {
       scalearray[abs( leftpos - lineposarray[i] ) - 1].iRightpos = leftpos;
       scalearray[abs( leftpos - lineposarray[i] ) - 1].iLeftpos = lineposarray[i];
      }
      else
      {
       scalearray[abs( leftpos - lineposarray[i] ) - 1].iLeftpos = leftpos;
       scalearray[abs( leftpos - lineposarray[i] ) - 1].iRightpos = lineposarray[i];
      }
     
     }
    
    }
   lineposarray.Append( leftpos );
   }
  }
  else
  {
   rightpos -= len;
   if ( rightpos < leftpos )
   {
    *(lenarray + len - 1) = 1;
    lineposarray.Append( len );
    scalearray[len - 1].iRightpos = len;
    scalearray[len - 1].iLeftpos = 0;
   }
   else
   {
    for ( i = 0; i < lineposarray.Count(); i++ )
    {
     if ( *(lenarray + abs( rightpos - lineposarray[i] ) - 1) == 0 )
     {
      *(lenarray + abs( rightpos - lineposarray[i] ) - 1) = 1;
      if ( rightpos > lineposarray[i] )
      {
       scalearray[abs( rightpos - lineposarray[i] ) - 1].iRightpos = rightpos;
       scalearray[abs( rightpos - lineposarray[i] ) - 1].iLeftpos = lineposarray[i];
      }
      else
      {
       scalearray[abs( rightpos - lineposarray[i] ) - 1].iLeftpos = rightpos;
       scalearray[abs( rightpos - lineposarray[i] ) - 1].iRightpos = lineposarray[i];
      }
     
     }
    
    }
   lineposarray.Append( rightpos );
   }
  }
  needcontinue = false;
  for ( i = 0; i < L / 2; i++ )
  {
   if ( *(lenarray + i) == 0 )
   {
    len = i + 1;
    needcontinue = true;
    break;
   }
  }
 }
 // 输出文本
 ofstream fout;
 fout.open("c:\\output.txt");
 fout << lineposarray.Count() - 2 << "\n";
 for ( i = 2; i < lineposarray.Count(); i++ )
 {
  fout << lineposarray[i] << "  ";
 }
 fout << "\n";
 for ( i = 0; i < L; i++ )
 {
  fout << scalearray[i].iLen << "  ";
  fout << scalearray[i].iLeftpos << "  ";
  fout << scalearray[i].iRightpos << "  ";
  fout << "\n";
 }
 fout.flush();
 fout.close();
 delete [] lenarray;
 return;
}

 

 

 

posted on 2009-06-02 11:05  constant  阅读(2772)  评论(12)    收藏  举报