zoukankan      html  css  js  c++  java
  • Codeforces Round #600 (Div. 2) E. Antenna Coverage (DP)

    传送门

    思路见注释;

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pLL;
    const int N=2e5+5;
    const double inf=0x3f3f3f3f;
    #define ls (i<<1)
    #define rs (i<<1|1)
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define debug puts("...")
    LL read()
    {
        LL x=0,t=1;
        char ch=getchar();
        while(!isdigit(ch)){ if(ch=='-')t=-1; ch=getchar(); }
        while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
        return x*t;
    }
    //f[i] 为 [1,i] 被覆盖的最小花费
    int f[N],x[N],s[N];
    int main()
    {
        int n=read(),m=read();
        for(int i=0;i<=m;i++) f[i]=m;//把[1,i]看作[1,m]的子问题,覆盖[1,m] 最多花费 m,那么其子问题 覆盖[1,i] 最多需要 i;
        for(int i=1;i<=n;i++)
        {
            x[i]=read();
            s[i]=read();
        }
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
                if(x[j]<=i) f[i]=min(f[i],f[max(x[j]*2-i-1,0)]+max(i-x[j]-s[j],0));//第一种情况,让 x[j] 向后扩张覆盖 i 则需要至少 i-x[j]-s[j]的花费(扩张的花费,其可能为负,可能已经被覆盖了),x[j]是向两边同时扩张的,所以 算出 i关于 x[j] 对称的点的前一个位置
                else f[i]=min(f[i],f[max(x[j]-s[j]-1,0)] );//第二种情况,是否可能被后面的点直接覆盖掉(不扩张),在这里不考虑 后面的点扩张之后把前面的i覆盖的情况,因为 x[j] 向前扩张至i,同时也会向后扩张至 i 关于 x[j] 的对称点k, 对于k而言 的第一种种情况与 i的第二种情况等价(都是覆盖后,通过 f[i-1] 转移),所以没有必要,而且也避免了后效性。
        }
        printf("%d
    ",f[m]);
        return 0;
    }
     
    
  • 相关阅读:
    【SCOI 2011】 糖果
    【POJ 3159】 Candies
    【POJ 1716】 Integer Intervals
    【POJ 2983】 Is the information reliable?
    【POJ 1364】 King
    【POJ 1201】 Intervals
    【POJ 1804】 Brainman
    6月10日省中提高组题解
    【POJ 3352】 Road Construction
    【POJ 1144】 Network
  • 原文地址:https://www.cnblogs.com/DeepJay/p/12025177.html
Copyright © 2011-2022 走看看