1

I'm practicing ACM problems to become a better programmer, but I'm still fairly new to c++ and I'm having trouble interpreting some of the judges code I'm reading. The beginning of a class starts with

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

and then later it's initialized with

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

I'm trying to read the code but I can't make sense of that. The State class only seems to have 1 argument passed, but the programmer is passing 2 in his initialization. Also, what exactly is being set = to 1? As far as I can tell, the = operator isn't being overloaded but just in case I missed something I've included the full code below.

Any help would be greatly appreciated.

Thanks in advance

    /*
    * 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;
       }
Josh Horowitz
  • 655
  • 2
  • 6
  • 15

4 Answers4

6

You are confusing a call to state::operator()(int, int) with an initialization. That operator call lets you set the value of an element of the class instance.

State s(n);  // this is the only initialization
s(0,0) = 1;  // this calls operator()(int, int) on instance s
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Ahh I see, very interesting. What is the = 1 doing? – Josh Horowitz Mar 12 '13 at 14:26
  • @JoshHorowitz basically, the operator gives you access to elements in `s`. So `s(0,0)=1` assigns the value of `1` to the element in position `0,0`. Think of it as a kind of 2D array, or a matrix. – juanchopanza Mar 12 '13 at 14:36
0

In this line:

s(0,0) = 1;

it's calling this:

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

and because it returns a reference to a double, you can assign to it.

Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
0

The second line is no longer initialization. The constructor was invoked in line 1, the second line invokes

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

with n=0 and m=0 and writing 1 to the reference that is returned.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
0

This part:

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

...is a member initializer list. It's sort of similar to if you'd written the construct like:

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

...except that it initializes _n and _p instead of starting with them unitialized, then assigning values to them. In this specific case that may not make much difference, but when you have things like references that can only be initialized (not assigned) it becomes crucial.

The s(0,0) = 1 looks like s is intended to act a little like a 2D array, and they've overloaded operator() to act as a subscripting operator for that array. I posted a class that does that in a previous answer.

Community
  • 1
  • 1
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111