1

私はより良いプログラマーになるために ACM の問題を練習していますが、まだ C++ にはかなり慣れていないため、読んでいるジャッジ コードの一部を解釈するのに苦労しています。クラスの始まりは

public:
   State(int n) : _n(n), _p(2*n+1)
   {

その後、次のように初期化されます

State s(n);
s(0,0) = 1;

コードを読み取ろうとしていますが、意味がわかりません。State クラスには引数が 1 つしか渡されていないように見えますが、プログラマーは初期化で 2 つを渡しています。また、正確に = を 1 に設定しているのは何ですか? 私が知る限り、= 演算子はオーバーロードされていませんが、何かを見逃した場合に備えて、以下に完全なコードを含めました。

どんな助けでも大歓迎です。

前もって感謝します

    /*
    * D - Maximum Random Walk solution
     * ICPC 2012 Greater NY Regional
     * Solution by Adam Florence
     * Problem by Adam Florence
     */

    #include <cstdio> // for printf
    #include <cstdlib> // for exit
    #include <algorithm> // for max
    #include <iostream>
    #include <vector>

    using namespace std;

    class State
    {
    public:
       State(int n) : _n(n), _p(2*n+1)
          {
          if (n < 1)
             {
             cout << "Ctor error, n = " << n << endl;
             exit(1);
             }
          for (int i = -n; i <= n; ++i)
             _p.at(i+_n) = vector<double>(n+1, 0.0);
          }

       void zero(const int n)
          {
          for (int i = -n; i < n; ++i)
             for (int m = 0; m <= n; ++m)
                _p[i+_n][m] = 0;
          }

       double operator()(int i, int m) const
          {
    #ifdef DEBUG
          if ((i < -_n) || (i > _n))
             {
             cout << "Out of range error, i = " << i << ", n = " << _n << endl;
             exit(1);
             }
          if ((m < 0) || (m > _n))
             {
             cout << "Out of range error, m = " << m << ", n = " << _n << endl;
             exit(1);
             }
    #endif
          return _p[i+_n][m];
          }

       double& operator()(int i, int m)
          {
    #ifdef DEBUG
          if ((i < -_n) || (i > _n))
             {
             cout << "Out of range error, i = " << i << ", n = " << _n << endl;
             exit(1);
             }
          if ((m < 0) || (m > _n))
             {
             cout << "Out of range error, m = " << m << ", n = " << _n << endl;
             exit(1);
             }
    #endif
          return _p[i+_n][m];
          }

       static int min(int x, int y)
       {
           return(x < y ? x : y);
       }
       static int max(int x, int y)
       {
           return(x > y ? x : y);
       }

    private:
       int _n;

       // First index is the current position, from -n to n.
       // Second index is the maximum position so far, from 0 to n.
       // Value is probability.
       vector< vector<double> > _p;
    };

    void go(int ds)
       {
       // Read n, l, r
       int n, nds;
       double l, r;
       cin >> nds >> n >> l >> r;
       const double c = 1 - l - r;

       if(nds != ds){
           cout << "Dataset number " << nds << " does not match " << ds << endl;
           return;
       }

       // Initialize state, probability 1 at (0,0)
       State s(n);
       s(0,0) = 1;

       State t(n);

       State* p1 = &s;
       State* p2 = &t;

       for (int k = 1; k <= n; ++k)
          {
          // Compute probabilities at step k

          p2->zero(k);

          // At step k, the farthest from the origin you can be is k
          for (int i = -k; i <= k; ++i)
             {
              const int mm = State::min( State::max(0, i+k), k);
             for (int m = 0; m <= mm; ++m)
                {
                // At step k-1, p = probability of (i,m)
                const double p = p1->operator()(i,m);
                if (p > 0)
                   {
                   // Step left
                   p2->operator()(i-1, m) += p*l;
                   // Step right
                   p2->operator()(i+1, State::max(i+1,m)) += p*r;
                   // Stay put
                   p2->operator()(i, m) += p*c;
                   }
                }
             }
          swap(p1, p2);
          }

       // Compute expected maximum position
       double p = 0;
       for (int i = -n; i <= n; ++i)
          for (int m = 0; m <= n; ++m)
             p += m * p1->operator()(i,m);

       printf("%d %0.4f\n", ds, p);
       }

    int main(int argc, char* argv[])
       {
       // Read number of data sets to process
       int num;
       cin >> num;

       // Process each data set identically
       for (int i = 1; i <= num; ++i)
          go(i);

       // We're done
       return 0;
       }
4

4 に答える 4

6

への呼び出しと初期化を混同しstate::operator()(int, int)ています。この演算子呼び出しにより、クラス インスタンスの要素の値を設定できます。

State s(n);  // this is the only initialization
s(0,0) = 1;  // this calls operator()(int, int) on instance s
于 2013-03-12T14:14:10.343 に答える
0

この部分:

State(int n) : _n(n), _p(2*n+1)

...メンバー初期化リストです。次のような構成を記述した場合と似ています。

state(int n) { _n = n; _p = 2*n+1; }

...ただし、初期化され、初期化_nされ_pた状態で開始する代わりに、値が割り当てられます。この特定のケースでは大きな違いはないかもしれませんが、初期化しかできない (割り当てられない) 参照のようなものがある場合、それは非常に重要になります。

s(0,0) = 1ようなものsは、2D 配列のように動作することを意図しておりoperator()、その配列の添字演算子として機能するようにオーバーロードされています。以前の回答でそれを行うクラスを投稿しました。

于 2013-03-12T14:20:01.623 に答える
0

この行で:

s(0,0) = 1;

これを呼び出しています:

 double& operator()(int i, int m)

また、double への参照を返すため、それに割り当てることができます。

于 2013-03-12T14:15:16.587 に答える
0

2行目はもはや初期化ではありません。コンストラクターは 1 行目で呼び出され、2 行目で呼び出します

double& operator()(int i, int m)

n=0 および m=0 で、返される参照に 1 を書き込みます。

于 2013-03-12T14:18:03.227 に答える