[Codeforces 1253E] Antenna Coverage

Dynamic programming solution

State:

dp[i]: the minimum cost to cover all positions from[0, i]. (left shift by 1 to get 0 index)

 

// if position i is already covered, then dp[i] is the same with dp[i - 1] or 0 if i is 0

dp[i] = i == 0 ? 0 : dp[i - 1];  

 

//if position i is not covered, for all antenna intervals that are on the left side of i,

diff = i - r[j];

dp[i] = Math.min(dp[i], diff + (l[j] - diff <= 0 ? 0 : dp[l[j] - diff - 1]));

 

Why do we only care about the intervals that are on the left side of i?

There are a few cases in general: 

1. trivial case: there is no interval to the right of i. Only considering intervals on left side gives the correct answer.

2. there is at least 1 interval to the right of i. This case has 2 sub-cases:

a. all the remaining uncovered positions (> i) are adjacent with i, i.e, there is a position k > i such that [i + 1, k] are all uncovered, [k + 1, m] are all covered. 

for this case, say we extend one of the interval on the right side to cover i with added cost d. Since there must be an extension or no extension needed to acheive:given an interval to left of i, use some cost to make this interval cover i - d. This means instead of extending an interval on the right side of i, we can just give this cost d to an interval on the left side to make i covered, without yielding a worse minCost.

b. there are uncovered positions (> i) that are separated with i by at least 1 interval to the right of i. 

for this case, when extending an interval to the right of i to cover i, we'll also possibly cover more initially uncovered positions to the right of this interval. Denote this right side interval as interval[j]; Pick one of these uncovered positions and denote it as k. Notice interval[j] is on the left side of k. So this case is covered when we calculate dp[k] and check all intervals to k's left side. 

 

As a result, for a given uncovered position i, only checking intervals to its left lead to the correct final answer. 

Initialization:

dp[i] = i + 1; Need cost of i + 1 in the worst case such that none of the positions in [0, i] is initially covered. 

 

Answer:

dp[m - 1], m is the max position that needs to be covered.

 

The runtime is O(n * m) and space is O(m).

    private static void solve(int q, FastScanner in, PrintWriter out) {
        for(int c = 0; c < q; c++) {
            int n = in.nextInt(), m = in.nextInt();
            int[][] intervals = new int[n][2];
            for(int i = 0; i < n; i++) {
                int start = in.nextInt() - 1;
                int diff = in.nextInt();
                intervals[i][0] = start - diff;
                intervals[i][1] = start + diff;
            }

            int[] dp = new int[m];
            for(int i = 0; i < m; i++) {
                dp[i] = i + 1;
                boolean covered = false;
                for(int j = 0; j < n; j++) {
                    if(intervals[j][0] <= i && intervals[j][1] >= i) {
                        covered = true;
                        break;
                    }
                }
                if(covered) {
                    dp[i] = i == 0 ? 0 : dp[i - 1];
                }
                else {
                    for(int j = 0; j < n; j++) {
                        if(intervals[j][0] > i) {
                            continue;
                        }
                        int diff = i - intervals[j][1];
                        dp[i] = Math.min(dp[i], diff + (intervals[j][0] <= diff ? 0 : dp[intervals[j][0] - diff - 1]));
                    }
                }
            }
            out.println(dp[m - 1]);
        }
        out.close();
    }

 

posted @ 2019-11-18 08:53  Review->Improve  阅读(503)  评论(0编辑  收藏  举报