E. Antenna Coverage (dp)


傳送門

題意: 在一個一維坐標上,有 n 個東西, 每個東西, 用 xi, si 表示 這個東西在 xi 位置上,

   它能覆蓋到的區間為 [ xi - si, xi + si ]; 

   然后, 你可以對任意的東西,  擴大它的 覆蓋區間, 即對 si 加 1; 花費1;

   問你 覆蓋 [ 1, m ] 的最少花費。

   n <= 80, m <= 100000;

解: 顯然 DP; 

   我們用 dp[ i ] 表示 覆蓋 i ~ m 的最少花費。

   然后我們從 m ~ 1 枚舉 x;

  若這個x 被某個東西覆蓋, 則 dp[ i ] = dp[ i + 1 ];

  否則, 枚舉 所有的 n 個東西, 判斷 那些 xi - si 大於你當前枚舉的那個 x 的東西。

  那么你設 dis = xi - si - x; 即你到那個東西覆蓋的區間的左端點的距離。

  然后, 因為它左邊擴了 dis, 那么它右邊也可以擴 dis;

  那么,答案就是 dis + dp[ xi + si + dis];

  然后, 最后 dp[ 1 ] 就是答案了。

  

#include <bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
struct note {
    int l, r;
}a[100];
bool cmp(note a, note b) {
    return a.l == b.l ? a.r < b.r : a.l < b.l;
}
const int N = 2e5 + 5;
int dp[N];
int main() {

    int n, m; scanf("%d %d", &n, &m);
    for(int i = 0; i <= m; i++) dp[i] = INF;
    int ma = 0;
    for(int i = 1; i <= n; i++) {
        int x, s; scanf("%d %d", &x, &s);
        a[i].l = max(x - s, 1); a[i].r = min(x + s, m);
        ma = max(ma, a[i].r);
        for(int j = a[i].l; j <= a[i].r; j++) {
            dp[j] = 0;
        }
    }
    for(int i = m; i > ma; i--) dp[i] = m - i + 1;
//    n++; a[n].l = n; a[n].r = n;
    sort(a + 1, a + 1 + n, cmp);
    dp[m + 1] = 0;
    for(int i = m; i >= 1; i--) {
        if(dp[i] == 0) dp[i] = dp[i + 1];
        else {
            for(int j = 1; j <= n; j++) {
                if(a[j].l > i) {
                    int dis = a[j].l - i;
                    int R = min(a[j].r + dis, m);
                    dp[i] = min(dp[i], dis + dp[R + 1]);
                }
            }
        }
    }
    printf("%d\n", dp[1]);
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM