羅区P4480 [[BJWC2018]ナプキン計画問題

この質問とネットワークフロー\(24 \)ナプキンのタイトルは実際には同じではない予定\([\) \(BJWC \) \(2018 \) \(] \)問題を計画するデータナプキンの大きな範囲。

連続でレストラン\(N \)日、ナプキンの数が必要な毎日が異なります。いま、最初の\(私は\)の日\((\) \(I \) \(= \) \(1 \) \(、\) \(2 \) \(、\) \(... \) \(、\) \(N- \) \()\)が必要です\(RI \)ブロックナプキンを。レストランでは、いつでも新しいナプキンを購入することができ、各ナプキンのコストは\(のP- \)

古いナプキンを使用し、あなたは、クリーニング後を再利用する必要があります。古いナプキンショップきれいにする\(\)を待つ必要があり、\(M1 \) $ C1 $の費用で、新しいナプキンを取得する日、店の$ B $をきれいにする古いナプキン、待つ$の必要性平方メートル$日間$ C2 $の費用で、新しいナプキンを取得します。

たとえば、$ A $清掃を清掃格納するために使用される、k番目の天使ナプキン、$ K $ $ + $ $ M1 $日で使用することができます。

データの50%については、我々は非常に古典的なネットワークフローアプローチを持っている:ナプキンは、問題を計画します

しかし、データの規模の拡大後に明らかにそれは、ネットワークフローでは解決することはできません。

二つの例:

\(1 \) クイックウォッシュ店は、より高価です。:

購入する前に考慮に入れるとナプキンを買うと回答がプロセスに影響を与えないだろう、とするときナプキンに$ Cは$バーを購入することは、明らかに、$ C $ $ + $ $ k個の$コストより$ C $ $ +より最適解に到達しました$ $ K $ $ + $ $ 1 $以下を過ごすために。

そして、ライセンスは難しい感情的なコストCK CK-1よりも(お金の増加を行い、最適な状況で使用ナプキン迅速な洗浄ショップ数回)以下に過ごすことではありません。

だから我々は三点を解決することができます。

スローウォッシュ店とのこれ以上の時間まで、新しいタオルを使用して最も安いどうやら最初は、最悪の答えを使用してクイックウォッシュ店を来る、あなたがキュー(つまり、かなり嫌である維持することができます使用して、Iちょうど3時間以上のための別の曲のコードで、今私はコードが理解していないと解釈されて説明させてあります。)

2.迅速な洗浄ポイントは安いです。

ほとんどこれは明白である、洗います。

これは素敵なコードです

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=200010;
const int INF=2147483647;
inline int read(){
    int X=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')X=(X<<1)+(X<<3)+ch-'0',ch=getchar();
    return X*w;
}
int t[N],num[N],q[N],cnt,d,n1,n2,c1,c2,tc;
int sn,sm,so,en,em,eo;
inline void add(int x,int p){
    q[en]=x;num[en++]=p;
}
int f(int k){
    sn=sm=so=en=em=eo=0;
    int ans=(tc-c2)*k;
    add(-2000000,k);
    for(int i=1;i<=d;i++){
        int j=t[i];
        while(sn!=en&&i-q[sn]>=n1){
            num[em]=num[sn];
            q[em++]=q[sn++];
        }
        while(sm!=em&&i-q[sm]>=n2){
            num[eo]=num[sm];
            q[eo++]=q[sm++];
        }
        while(j>0){
            if(so!=eo){
                if(num[eo-1]>j){
                    ans+=c2*j;
                    num[eo-1]-=j;
                    break;
                }
                else{
                    ans+=c2*num[eo-1];
                    j-=num[eo-1];
                    eo--;
                }
            }
            else if(sm!=em){
                if(num[em-1]>j){
                    ans+=c1*j;
                    num[em-1]-=j;
                    break;
                }
                else{
                    ans+=c1*num[em-1];
                    j-=num[em-1];
                    em--;
                }
            }
            else return INF;
        }
        add(i,t[i]);
    }
    return ans;
}
int sfen(int l,int r){
    while(233){
        if(r-l<=2){
            int m=INF;
            for(int i=l;i<r;i++)m=min(m,f(i));
            return m;
        }
        int mid1=l+(r-l)/3,mid2=l+2*(r-l)/3;
        int a=f(mid1);
        if(a!=INF&&a<=f(mid2))r=mid2;
        else l=mid1;
    }
}
int main(){
    d=read(),n1=read(),n2=read(),c1=read(),c2=read(),tc=read();
    if(n1>n2){swap(n1,n2);swap(c1,c2);}
    if(c1<=c2)n2=2000001,c2=101;
    int tsum=0;
    for(int i=1;i<=d;i++){
        t[i]=read();tsum+=t[i];
    }
    printf("%d\n",sfen(0,tsum+1));
    return 0;
}

おすすめ

転載: www.cnblogs.com/errichto/p/11317278.html