CF1253Eアンテナカバレッジ(DP)

この質問は難易度の正しさを証明しました。

オーダー\(F_iとは\)を表し([1、i]を\ \ ) 最小コストが完全に覆われています。答えは(F_M \)\

最初は間隔追加することがわかった\([0,0する] \)の答えには影響を与えません。だから、\(のf_i \)初期値のは次のように設定することができます\(I \) (これは非常に重要であり、適切ではないではありません!)

転送、場合\(Iは\)から完全にし、いくつかの初期の間隔を、被覆されている\(F_ {I-1} \) 転送します。

その後、各間隔を列挙する場合は区間内の右のポイント\(I \)左、この間隔がちょうど十分な拡張をカバーするために計算されます(I \)\した後、左のエンドポイント。すなわちから\(F _ {\ MAX( 0、L [J] - (IR [J]))} + IR [J] \) によって転送されます。

各セクションは、拡張された状態に揚げされる内容をメモは、拡張が初期間隔から開始しています。

時間複雑\(O(nm)を\)

彼は正当化し始めました。

、唯一の区間の左側をカバー右を検討する必要性を証明しない最初の考えてみましょう。

実際には、右を覆う部分も考慮され、これらの点をスキップする移すとき(このセクションで膨張した後です)。そこで、制御されません。

そして、最初の範囲から拡大し始めたことを証明最適なソリューションです。

あなたはポイントに拡大することを示し、範囲の拡大に基づいて拡大していくために必要がある場合は、\(私は\)ポイントへの最後の展開でなければなりません(J \)\に展開する権利(私は\)\後左の点間隔はスキップされている必要があります\(J \) そして、我々は使用する最後です\(I \)この最初の拡張の真ん中が必要ではないので、(なぜなら拡大を継続する必要性)状態。

だから、これは起こることができません。

次の展開は、カバーにちょうど十分な証明(\ I)\最適解である以上カバーするために拡張する必要はありません最適な解決策であり、(私は\)\少し。

あなたはより多くの拡張が必要な場合は、間隔が短くなっていることを左のように、左に多くのポイントをカバーすることができるので、それがなければなりません(以上カバーにか、他\(I \)場所\(のf_iは\)完全に不要です)。

しかし、インターバルの付加\([0,0] \) はい、このにおけるその役割)は、存在しなければならない\(+ F_ {I}。1 \ルF_iと+。1 \) ためにカバー\(I \)の間隔)は、更に、グリッドを拡張することができます。

間隔はもっと良いはずスキップする権利の移転後の点はそう。それはに拡張する必要はありません\(I \)を右に。

だから、これは右にあります。


コード

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=100010;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
    char ch=getchar();ll x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int n,m,x[maxn],s[maxn],f[maxn]; 
int main(){
    n=read();m=read();
    FOR(i,1,n) x[i]=read(),s[i]=read();
    f[0]=0;
    FOR(i,1,m){
        f[i]=i;
        bool flag=false;
        FOR(j,1,n) if(x[j]+s[j]>=i && x[j]-s[j]<=i) flag=true;
        if(flag) f[i]=f[i-1];
        FOR(j,1,n) if(x[j]+s[j]<i) f[i]=min(f[i],f[max(0,2*x[j]-i-1)]+i-(x[j]+s[j]));
    }
    printf("%d\n",f[m]);
}

おすすめ

転載: www.cnblogs.com/1000Suns/p/11919065.html