zoukankan      html  css  js  c++  java
  • BOI 2003 Problem. Spaceship

    题目

    The Romanian Space Association (RSA) discovered a new asteroid, which they called BOI2003. RSA is eager to
    explore the asteroid BOI2003, so they built a spaceship to carry scientists to the asteroid. The spaceship they built
    has some peculiar features. When the spaceship leaves Earth for the first time it should carry exactly S scientists.
    When the spaceship arrives at the asteroid BOI2003, a single scientist lands and the spaceship returns to take over
    other S scientists.
    The first scientist that landed on BOI2003 suspects the existence of a dangerous virus on the asteroid. Thus he
    suggests that, until the research is over, not a single scientist that traveled to BOI2003 should leave the spaceship
    when it arrives to Earth.
    To be more specific, let’s assume that the scientists are denoted by integers starting at 1. The spaceship works in
    the following way:
    – the first time it leaves Earth, the spaceship carries the scientists 1, 2, ..., S; one of these scientists lands on the
    asteroid and the other S-1 scientists return to Earth (but do not get off the ship);
    – the second time the spaceship leaves Earth, the scientists S+1, S+2, ..., 2S gather the S-1 scientists that came
    back, and the spaceship carries these 2S-1 scientists to BOI2003; one of them lands on the asteroid and the
    spaceship returns to Earth with 2S-2 scientists (again, they do not get off the ship);
    – the third time, the scientists 2S+1, 2S+2, ..., 3S together with the other 2S-2 scientists who already are on
    the spaceship, travel to BOI2003 and one of them lands on the asteroid;
    – and so on.
    After N rides, a research team consisting of N scientists has been carried over and is working on the asteroid
    BOI2003.
    Task
    Write a program that determines the number of possibilities to form the research team.
    Input data (file: ship.in)
    The single line of the input file contains the integers S and N, separated by a single space.
    Output data (file: ship.out)
    The single line of the output file contains an integer K, representing the number of possibilities to form the
    research team.
    Constraints
    1 ≤ S ≤ 10
    1 ≤ N ≤ 40
    The spaceship has unlimited capacity.
    The order in which the members of the team arrive on the asteroid does not matter.
    Example
    ship.in ship.out
    2 3 14
    Time limit: 0.4 seconds/test.

    分析

    看完题目其实就会有一个第一感觉,这道题的本质是一道数学题。这时候就要掏出纸和笔打草稿做计算。翻译过来,这道题就是:有一些人,先从前s个人里选一个,再从前2s个人里选一个……求这样选的方法数。

    这题的精髓在于首先要找到这道题目与组合之间的关系。然后再发现这些数字组成的序列其实是一个杨辉三角。

    在我的程序当中,我用一个init函数来计算C数组当中存储的数字(杨辉三角第s行),C[i]对应的是Cis

    init函数的写法是有点技巧的。因为对于计算一个C[j]需要用到的两个数字是上一行的C[j]和C[j-1],而如果从左往右计算,就会发现需要用的数字已经被更新过了。所以要做的是从右往左算。这样可以让本来需要开一个二维数组或者要写几行代码的函数变得非常简洁明了。

    接下来有一个f数组,f[i][j]表示i个s人小组里选出j个人的可能情况数量。想到就是C[k]*f[i-1][j-k]的和。也就是i-1个小组选j-k个人的情况数。

    (千万别忘了初始化数组233,调了好久)

    程序

    (第一个程序有高精度算法,添加了运算符重载。当然如果你只想了解核心算法,只要看第二段程序就可以了。两段程序在本质上是相同的。)

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int MAX = 100; 
      4 struct BIG
      5 {
      6     int len, s[MAX];
      7     BIG()
      8     {
      9         memset(s, 0, sizeof(s));
     10         len = 1;
     11     }
     12     BIG(int num)
     13     {
     14         *this = num;
     15     }
     16     BIG(const char* num)
     17     {
     18         *this = num;
     19     }
     20     BIG operator = (int num)
     21     {
     22         char s[MAX];
     23         sprintf(s, "%d", num);
     24         *this = s;
     25         return *this;
     26     }
     27     string str() const
     28     {
     29         string res = "";
     30         for(int i = 0; i < len; i++)
     31             res = (char)(s[i] + '0') + res;
     32         if(res == "") res = "0";
     33         return res;
     34     }
     35     void clean()
     36     {
     37         while(len > 1 && !s[len-1])
     38             len--;
     39     }
     40     BIG operator = (const char* num)
     41     {
     42         len = strlen(num);
     43         for(int i = 0; i < len; i++)
     44             s[i] = num[len-i-1] - '0';
     45         return *this;
     46     }
     47     BIG operator + (const BIG& b) const
     48     {
     49         BIG c;
     50         c.len = 0;
     51         for(int i = 0, g = 0; g || i < max(len, b.len); i++)
     52         {
     53             int x = g;
     54             if(i < len) x += s[i];
     55             if(i < b.len) x += b.s[i];
     56             c.s[c.len++] = x % 10;
     57             g = x / 10;
     58         }
     59         return c;
     60     }
     61     BIG operator * (const BIG& b)
     62     {
     63         BIG c; c.len = len + b.len;
     64         for(int i = 0; i < len; i++)
     65               for(int j = 0; j < b.len; j++)
     66                 c.s[i+j] += s[i] * b.s[j];
     67         for(int i = 0; i < c.len-1; i++)
     68         {
     69               c.s[i+1] += c.s[i] / 10;
     70               c.s[i] %= 10;
     71         }
     72         c.clean();
     73         return c;
     74     }
     75     BIG operator - (const BIG& b) {
     76         BIG c;
     77         c.len = 0;
     78         for(int i = 0, g = 0; i < len; i++)
     79         {
     80             int x = s[i] - g;
     81             if(i < b.len)
     82                 x -= b.s[i];
     83             if(x >= 0)
     84                 g = 0;
     85             else
     86             {
     87                 g = 1;
     88                 x += 10;
     89             }
     90             c.s[c.len++] = x;
     91         }
     92         c.clean();
     93         return c;
     94     }
     95     bool operator < (const BIG& b) const
     96     {
     97         if(len != b.len)
     98             return len < b.len;
     99         for(int i = len-1; i >= 0; i--)
    100             if(s[i] != b.s[i])
    101                 return s[i] < b.s[i];
    102         return false;
    103     }
    104     bool operator > (const BIG& b) const
    105     {
    106         return b < *this;
    107     }
    108     bool operator <= (const BIG& b)
    109     {
    110         return !(b > *this);
    111     }
    112     bool operator == (const BIG& b)
    113     {
    114         return !(b < *this) && !(*this < b);
    115     }
    116     BIG operator += (const BIG& b)
    117     {
    118         *this = *this + b;
    119         return *this;
    120     }
    121 };
    122 ostream& operator << (ostream &out, const BIG& x)
    123 {
    124     out << x.str();
    125     return out;
    126 }
    127 long long s, p, n;
    128 BIG f[60][60], C[20];
    129 void init(int n)
    130 {
    131     for (int i = 2; i <= n; i++)
    132         for (int j = i; j >= 1; j--)
    133             C[j] = C[j] + C[j-1];
    134 }
    135 int main()
    136 {
    137     freopen("spaceship.in","r",stdin);
    138     freopen("spaceship.out","w",stdout);
    139     cin >> s >> n;
    140     C[0] = 1, C[1] = 1;
    141     
    142     //Initiate combination array
    143     init(s);
    144     f[0][0] = 1;
    145     for (int i = 1; i <= n; i++)
    146     {
    147         for (int j = 0; j <= i; j++)
    148         {
    149             if (j < i)
    150                 p = 0;
    151             else
    152                 p = 1;
    153             for (int k = p; k <= j; k++)
    154                 f[i][j] += C[k]*f[i-1][j-k];
    155         }
    156     }
    157     cout << f[n][n] << endl;
    158     return 0;
    159 }
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 long long C[11], s, f[41][41], p, n;
     4 void init(int n)
     5 {
     6     for (int i = 2; i <= n; i++)
     7         for (int j = i; j >= 1; j--)
     8             C[j] = C[j] + C[j-1];
     9 }
    10 int main()
    11 {
    12     freopen("spaceship.in","r",stdin);
    13     freopen("spaceship.out","w",stdout);
    14     cin >> s >> n;
    15     C[0] = 1, C[1] = 1;
    16     
    17     init(s);
    18     f[0][0] = 1;
    19     for (int i = 1; i <= n; i++)
    20     {
    21         for (int j = 0; j <= i; j++)
    22         {
    23             if (j < i)
    24                 p = 0;
    25             else
    26                 p = 1;
    27             for (int k = p; k <= j; k++)
    28                 f[i][j] += C[k]*f[i-1][j-k];
    29         }
    30     }
    31     cout << f[n][n] << endl;
    32     return 0;
    33 }
  • 相关阅读:
    OC语言前期准备
    C语言指针
    C语言字符串
    C语言数组
    python语法
    shell脚本命令 运行python文件&python命令行运行python代码
    HTTP Status完整枚举
    CRON表达式
    mybatis-generator生成的mapper中的
    iOS事件的响应和传递机制
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/8313087.html
Copyright © 2011-2022 走看看