isti757's blog

By isti757, 9 years ago, In English

I wrote a different solution to Topcoder 647 DIV1 500 problem and can't understand why is it giving different (larger) results.

I brute force over all the sets of robots and then order each set increasingly by capacity. Then all robots travel together only so much that the robot with the least capacity can come back and compensate all the robots that have still not turned back, such that their capacity is again full. Once the robot has compensated all the others in full, it comes back and we apply the same logic to the robots left.

What is wrong with my logic?

Here is the code (note that it doesn't work for test cases larger than 31 in size):

class CtuRobots {
public:
    double brute(vector<double> &use) {
        sort(use.begin(), use.end());

        int n = use.size();
        vector<double> x(use.size(), 0);
        for(int i = 0; i < n; i++) {
            // subtract from the current capacity the way back
            // the rest is guaranteed to be non-negative
            double cur = use[i];
            for(int j = 0; j < i; j++)
                cur -= x[j];
            assert(cur >= 0.0);

            // split the left over capacity over the robots
            // that have still not turned back plus 2 times for the current
            // robot that has to go forward and then back
            cur /= (n-i+1);
            x[i] = cur;
        }

        // the answer is the sum of all the segments
        double ans = 0;
        for(int i = 0; i < x.size(); i++)
            ans += x[i];

        // check that we actually use all the fuel
        double chk = 0, sum = 0;
        for(int i = 0; i < x.size(); i++) {
            chk += (use.size()-i)*x[i];
            sum += use[i];
        }
        assert(abs(2*chk-sum) < 1e-9);

        return ans;
    }

    double maxDist(int B, vector <int> cost, vector <int> cap) {
        // brute force solution
        assert(cost.size() < 32);
        double brt = 0;
        for(int i = 0; i < (1 << cost.size()); i++) {
            int cur = 0;
            vector<double> use;
            for(int j = 0; j < cost.size(); j++) {
                if(i & (1 << j)) {
                    cur += cost[j];
                    use.push_back(cap[j]);
                }
            }
            if(cur <= B) {
                brt = max(brt, brute(use));
            }
        }

        // dynamic programming solution
        for(int i = 0; i < cost.size(); i++) {
            for(int j = 0; j < i; j++) {
                if(cap[j] > cap[i]) {
                    swap(cap[i], cap[j]);
                    swap(cost[i], cost[j]);
                }
            }
        }

        double dp[111111];
        for(int i = 0; i <= B; i++)
            dp[i] = 0;

        for(int i = 0; i < cost.size(); i++) {
            for(int j = B-cost[i]; j >= 0; j--) {
                dp[j+cost[i]] = max(dp[j]/3.0+cap[i], dp[j+cost[i]]);
            }
        }

        double ans = 0;
        for(int i = 0; i <= B; i++) {
            ans = max(ans, dp[i]/2.0);
        }

        assert(abs(ans-brt) < 1e-9);
        assert(brt >= ans);
        return ans;
    }
};

int main( int argc, char* argv[] ) {
    {
        int costARRAY[] = {50,25};
        vector <int> cost( costARRAY, costARRAY+ARRSIZE(costARRAY) );
        int capARRAY[] = {1,1};
        vector <int> cap( capARRAY, capARRAY+ARRSIZE(capARRAY) );
        CtuRobots theObject;
        eq(0, theObject.maxDist(100, cost, cap),0.6666666666666666);
    }
    {
        int costARRAY[] = {23,5,8,20,15};
        vector <int> cost( costARRAY, costARRAY+ARRSIZE(costARRAY) );
        int capARRAY[] = {108,30,42,100,94};
        vector <int> cap( capARRAY, capARRAY+ARRSIZE(capARRAY) );
        CtuRobots theObject;
        eq(1, theObject.maxDist(25, cost, cap),55.0);
    }
    {
        int costARRAY[] = {0,0,0,1000,1000,0,1000,0};
        vector <int> cost( costARRAY, costARRAY+ARRSIZE(costARRAY) );
        int capARRAY[] = {2039,4819,5923,1577,8749,9182,3652,4918};
        vector <int> cap( capARRAY, capARRAY+ARRSIZE(capARRAY) );
        CtuRobots theObject;
        eq(2, theObject.maxDist(1382, cost, cap),6503.238683127572);
    }
    {
        int costARRAY[] = {185,130,109,1,45,117,127,13,2,37,6,1,2};
        vector <int> cost( costARRAY, costARRAY+ARRSIZE(costARRAY) );
        int capARRAY[] = {93,5,278,4,20,54,93,213,103,5,225,32,5};
        vector <int> cap( capARRAY, capARRAY+ARRSIZE(capARRAY) );
        CtuRobots theObject;
        eq(3, theObject.maxDist(209, cost, cap),190.48376771833563);
    }
    return 0;
}
  • Vote: I like it
  • +8
  • Vote: I do not like it

»
9 years ago, # |
  Vote: I like it 0 Vote: I do not like it

anyone?

»
9 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Your solution is correct. I've tested it at Practice Room few minutes ago.

  • »
    »
    9 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    the problem is the bruteforce solution doesn't agree with the dynamic programming one, even on the pretests.

  • »
    »
    9 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    the brute force solution uses different logic, heres the description once more:

    I brute force over all the sets of robots and then order each set increasingly by capacity. Then all robots travel together only so much that the robot with the least capacity can come back and compensate all the robots that have still not turned back, such that their capacity is again full. Once the robot has compensated all the others in full, it comes back and we apply the same logic to the robots left.

    I can't get why does it give different (better) result than the dynamic programming solution which passes systems tests. You can see it by running the entire code as posted. The assert assert(abs(ans-brt) < 1e-9); will fail on the 2nd test case with a better result by the bruteforce solver.

»
9 years ago, # |
  Vote: I like it 0 Vote: I do not like it

I think you read the problem incorrectly. Robot i can only give fuel to robot i+1 when i turns back, not to any other robot.