1. 程式人生 > >洛谷1251餐巾紙問題

洛谷1251餐巾紙問題

out clu org radius 決定 while gis con spa

題目戳這裏

題目描述

一個餐廳在相繼的N天裏,第i天需要Ri塊餐巾(i=l,2,…,N)。餐廳可以從三種途徑獲得餐巾。

(1)購買新的餐巾,每塊需p分;

(2)把用過的餐巾送到快洗部,洗一塊需m天,費用需f分(f<p)。如m=l時,第一天送到快洗部的餐巾第二天就可以使用了,送慢洗的情況也如此。

(3)把餐巾送到慢洗部,洗一塊需n天(n>m),費用需s分(s<f)。

在每天結束時,餐廳必須決定多少塊用過的餐巾送到快洗部,多少塊送慢洗部。在每天開始時,餐廳必須決定是否購買新餐巾及多少,使洗好的和新購的餐巾之和滿足當天的需求量Ri,並使N天總的費用最小

輸入輸出格式

輸入格式:

輸入文件共3行,第1行為總天數;第2行為每天所需的餐巾塊數;第3行為每塊餐巾的新購費用p,快洗所需天數m,快洗所需費用f,慢洗所需天數n,慢洗所需費用s。

輸出格式:

輸出文件共1行為最小的費用。

輸入輸出樣例

輸入樣例#1: 復制
3
3 2 4
10 1 6 2 3
輸出樣例#1: 復制
64

說明

N<=2000

ri<=10000000

p,f,s<=10000

時限4s

學習了一下zkw費用流,大概就是用dinic跑費用流,,快的飛起  

  建圖還很麻煩。把每天拆成ai,bi兩點,ai表示用過的,bi沒用過。建立超級源匯S,T。

  (1)S向ai連容量r[i],費用0的邊,S向bi連容量r[i],費用p的邊

  (2)bi向T連容量r[i],費用0的邊

  (3)ai向b(i+m)連容量無窮,費用f的邊,ai向b(i+n)連容量無窮,費用f的邊,ai向a(i+1)連容量無窮費用0的邊

  然後zkw 50ms過了

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
#define inf 0x3f3f3f3f
#define N 2005
using namespace std;
int day,n,m,p,s,f,S,T,tot,r[N],cur[N<<1],hd[N<<1],vis[N<<1],d[N<<1]; 
ll cost;
struct edge{int u,v,w,next,cap,flow;}e[N<<4];
void adde(int u,int v,int w,int c){
    e[tot].u=u;
    e[tot].v=v;
    e[tot].w=w;
    e[tot].cap=c;
    e[tot].next=hd[u];
    hd[u]=tot++;
}

bool spfa(){
    memset(d,0x3f,sizeof(d));
    memset(vis,0,sizeof(vis));
    deque<int>q;d[T]=0;q.push_back(T);
    while(!q.empty()){
        int u=q.front();q.pop_front();vis[u]=0;
        for(int i=hd[u];~i;i=e[i].next){
            if(e[i^1].cap<=e[i^1].flow)continue;
            int w=e[i^1].w,v=e[i].v;
            if(d[v]>d[u]+w){
                d[v]=d[u]+w;
                if(vis[v])continue;
                vis[v]=1;
                if(!q.empty()&&d[v]<d[q.front()])q.push_front(v);
                else q.push_back(v);
            }
        }
    }
    return d[S]<0x3f3f3f3f;
}

int dfs(int u,int a){
    if(!a||u==T)return a;
    vis[u]=1;int f=0,fl=0;
    for(int &i=cur[u];~i;i=e[i].next){
        int v=e[i].v;
        if(d[v]+e[i].w==d[u]&&!vis[v]&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
            cost+=(ll)f*e[i].w;fl+=f;
            e[i].flow+=f;
            e[i^1].flow-=f;
            a-=f;
            if(!a)break;
        }
    }
    vis[u]=0;return fl;
}

int main(){
#ifdef wsy
    freopen("data.in","r",stdin);
#else
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
#endif
    memset(hd,-1,sizeof(hd));
    scanf("%d",&day);S=0;T=(day<<1)+1;
    for(int i=1;i<=day;i++)scanf("%d",&r[i]);
    scanf("%d%d%d%d%d",&p,&m,&f,&n,&s);
    for(register int i=1;i<=day;i++){
        adde(S,i,0,r[i]);adde(i,S,0,0);
        adde(S,i+day,p,inf);adde(i+day,S,-p,0);
        if(i!=day)adde(i,i+1,0,inf),adde(i+1,i,0,0);
        adde(i+day,T,0,r[i]);adde(T,i+day,0,0);
        if(i+m<=day)adde(i,i+day+m,f,inf),adde(i+day+m,i,-f,0);
        if(i+n<=day)adde(i,i+day+n,s,inf),adde(i+day+n,i,-s,0);
    }
    while(spfa()){
        for(int i=S;i<=T;i++)cur[i]=hd[i];
        dfs(S,inf);
    }
    printf("%lld",cost);
    return 0;
}

  

洛谷1251餐巾紙問題