ycperson's blog

By ycperson, history, 6 hours ago, In English

I was doing this problem: https://codeforces.net/problemset/problem/1862/F and my approach to solving was to binary search on the time required, and the predicate for the search would be whether the time is enough -- determined by a DP check as follows: given some time t, we have w*t water and f*t fire available, so we try to use as much of the water as possible, and then see if enough fire remains. I don't understand why the following implementation of this idea does not work and was hoping someone could help:

bool possible(vector<int>& s, int a, int b, int n, int t) {
    // s1 = size of container 1 (how much water we have)
    // s2 = size of container 2 (how much fire we have)
    int s1 = t*a, s2 = t*b;
    
    // definition of dp[i][j][k]:
    // first i elements
    // using j of them
    // using or not using kth one
    // considering these i, j, k, what is the min space remaining in container 1?
    vector<vector<vector<int>>> dp(n+1, vector<vector<int>>(n+1, vector<int>(2, 1e15)));

    for (int i = 0; i <= n; i++) dp[i][0][0] = s1;

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            dp[i][j][0] = min(dp[i-1][j][0], dp[i-1][j][1]);

            for (int k = i-1; k >= j-1; k--) {
                int op1 = ((dp[k][j-1][0] != 1e15 && dp[k][j-1][0] >= s[i-1]) ? dp[k][j-1][0] - s[i-1] : 1e15);
                int op2 = ((dp[k][j-1][1] != 1e15 && dp[k][j-1][1] >= s[i-1]) ? dp[k][j-1][1] - s[i-1] : 1e15);

                dp[i][j][1] = min({dp[i][j][1], op1, op2});
            }
        }
    }
    
    int mn = s1;

    // take the min space left in container 1 across all possibilities
    for (int i = 0; i <= n; i++) {
        mn = min({mn, dp[n][i][0], dp[n][i][1]});
    }

    int sm = 0;
    
    for (auto i : s) sm += i;
    
    return (sm-(s1-mn) <= s2);
}

void solve() {
    int a, b, n;
    cin >> a >> b >> n;

    vector<int> s(n);

    for (int i = 0; i < n; i++) cin >> s[i];

    int curr = 0;
    
    // binary searching on the time required ("curr")
    for (int p = 30; p >= 0; p--) {
        int pwp = (1ll<<p);

        while (curr+pwp <= 1e6 && !possible(s, a, b, n, curr+pwp)) curr += pwp;
    }

    cout << curr+1 << endl;
}
 
signed main() {
    cin.tie(0)->sync_with_stdio(0);

    int t;
    cin >> t;
 
    while (t--) {
        solve();
    }
}
  • Vote: I like it
  • 0
  • Vote: I do not like it

»
6 hours ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by ycperson (previous revision, new revision, compare).

»
6 hours ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by ycperson (previous revision, new revision, compare).

»
6 hours ago, # |
  Vote: I like it 0 Vote: I do not like it

I just checked your submissions and saw you got AC a bit after posting this. Out of curiosity, what was the problem?

  • »
    »
    6 hours ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    I just followed the editorial's solution cuz I don't know what is wrong with mine lol

»
5 hours ago, # |
  Vote: I like it 0 Vote: I do not like it

Some variables (dp, op1, op2 and mn) can have a value that exceeds $$$2e9$$$, resulting in overflow. You can solve this by simply using long long for these variables.

Your solution seems otherwise fine. Does that fix the problem?

  • »
    »
    4 hours ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    I forgot to mention that i already put #define int ll before, so there’s no overflow issue.other than that, everything is in the code above.

    • »
      »
      »
      4 hours ago, # ^ |
        Vote: I like it +1 Vote: I do not like it

      Ohh, alright. I'll keep looking for the mistake, then.