cf Round 600 Antenna Coverage dp

Antenna Coverage

给定若n个区间,每次操作可以使一个区间左右拓宽1,求最小操作次数使得区间[1,m]均被覆盖.
考虑dp:
dp[i]=区间[i,m]均被覆盖的最小花费
转移:
d p [ i ] = d p [ i + 1 ] dp[i]=dp[i+1] dp[i]=dp[i+1],如果 [ 1 , i ] [1,i] [1,i]被原始区间覆盖.
否则, p = l − i , d p [ i ] = m i n ( p + d p [ r + p + 1 ] ) , ( l > = i ) p=l-i,dp[i]=min(p+dp[r+p+1]),(l>=i) p=li,dp[i]=min(p+dp[r+p+1]),(l>=i)
(当r+p+1>m时,令小标为m+1,即如果[l,r]区间拓宽至i,而右区间此时已经超过了m,该操作的代价就只有p)
所以,初始化 d p [ m + 1 ] = 0 , d p [ i ] = m − i + 1 dp[m+1]=0,dp[i]=m-i+1 dp[m+1]=0,dp[i]=mi+1(可能花费最大值)
答案就是dp[1]

#include
using namespace std;
char buf[1<<20],*P1=buf,*P2=buf;
#define gc() (P1==P2&&(P2=(P1=buf)+fread(buf,1,1<<20,stdin),P1==P2)?EOF:*P1++)
#define TT templateinline
TT bool read(T &x){
    x=0;char c=gc();bool f=0;
    while(c<48||c>57){if(c==EOF)return 0;f^=(c=='-'),c=gc();}
    while(47<c&&c<58)x=(x<<3)+(x<<1)+(c^48),c=gc();
    if(f)x=-x;
    return 1;
}
TT bool read(T&a,T&b){return read(a)&&read(b);}
TT bool read(T&a,T&b,T&c){return read(a)&&read(b)&&read(c);}
typedef long long ll;
const ll MAXN=2e5+8,mod=1e9+8,inf=0x3f3f3f3f;
#define lowbit(x) (x&(-x))
struct Node{int x,s;}a[88];
int n,m,dp[MAXN];
int main() {
    read(n,m);
    for(int i=0;i<n;++i)read(a[i].x,a[i].s);
    for(int i=m;i>=0;--i){
        int flag=0;
        for(int j=0;j<n;++j){//i是否被覆盖
            if(a[j].x-a[j].s<=i&&i<=a[j].x+a[j].s){
                dp[i]=dp[i+1];
                flag=1;
                break;
            }
        }
        if(flag)continue;
        dp[i]=m-i+1;
        for(int j=0;j<n;++j){
            if(a[j].x-a[j].s>=i){
                int p=a[j].x-a[j].s-i;
                dp[i]=min(dp[i],p+dp[min(a[j].x+a[j].s+1+p,m+1)]);
                //a[j].x+a[j].s该点已经覆盖了,所以要+1
            }
        }
    }
    printf("%d",dp[1]);
    return 0;
}

你可能感兴趣的:(DP,模板)