1. 程式人生 > >並不對勁的餐巾計劃問題

並不對勁的餐巾計劃問題

closed dig define src esp ++ std 輸入輸出格式 max

********************題目略長**********************

題目描述

一個餐廳在相繼的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行為最小的費用。

輸入輸出樣例

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

說明

N<=2000

ri<=10000000

p,f,s<=10000

時限4s

*************在網絡流24題中算是神奇的一題************

網絡流24題中,存在各種只是來讓人練寫模板熟練度的題。不過這題的建圖方式算是一股清流,讓人很不好想,但想到了也很不好證明,不過證明出來後真的很好寫。

對於送到快洗部、慢洗部、直接購買都很好想,拆點後直接連就行了。也就是把一天拆成上午和下午兩個點,上午可以接受洗完的餐巾、買新餐巾,下午可以把餐巾送去洗。也就是說,上午的“流”的意義是幹凈的餐巾,下午的“流”的意義是臟的餐巾。

讓第i天“經過”匯點的流為ni顯然是行不通的。可以把“拿去用ni個餐巾”拆成兩個動作:上午把ni個幹凈的餐巾給匯點,下午接收從源點來的ni個臟餐巾。

還要註意的是,餐廳裏可以攢幹凈的餐巾,所以第i天上午要連一條邊到第i+1天上午。

以上過程其實可以用有上下界網絡流來思考,但並不對勁的人並不想這麽做。

技術分享圖片
#include<iostream>
#include
<iomanip> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #define ll long long #define maxn 4010 #define maxm 2000010 using namespace std; const ll inf=0x7fffffff; ll fir[maxn],nxt[maxm],v[maxm],fl[maxm],w[maxm],cnt; ll mincost,n,m,p,f,s,N,dis[maxn]; bool vis[maxn]; ll read() { ll x=0,f=1; char ch=getchar(); while(isdigit(ch)==0 && ch!=-) ch=getchar(); if(ch==-)f=-1,ch=getchar(); while(isdigit(ch))x=x*10+ch-0, ch=getchar(); return x*f; } void addedge(ll u1,ll v1,ll fl1,ll w1) { w[cnt]=w1,v[cnt]=v1,fl[cnt]=fl1,nxt[cnt]=fir[u1],fir[u1]=cnt++; w[cnt]=-w1,v[cnt]=u1,fl[cnt]=0,nxt[cnt]=fir[v1],fir[v1]=cnt++; } ll spfa() { memset(dis,-1,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[N*2+1]=0; deque<ll >q; q.push_back(N*2+1); while(!q.empty()) { ll u=q.front();q.pop_front(); for(ll k=fir[u];k!=-1;k=nxt[k]) { ll vv=v[k]; if(fl[k^1]>0) { if(dis[vv]>dis[u]-w[k] || dis[vv]==-1) { dis[vv]=dis[u]-w[k]; if(vis[vv]==0) { if(q.empty()==0&& dis[q.front()]>dis[vv]) q.push_front(vv); else q.push_back(vv); } vis[vv]=1; } } } vis[u]=0; } return dis[0]; } ll getfl(ll u,ll nowflow) { vis[u]=1; if(u==N*2+1)return nowflow; ll tmp,sum=0; for(ll k=fir[u];k!=-1;k=nxt[k]) { if(nowflow<=0)break; ll vv=v[k]; if(vis[vv]==0 && fl[k]>0 && dis[vv]+w[k]==dis[u]&& (tmp=getfl(vv,min(nowflow,fl[k])))>0) { fl[k]-=tmp; fl[k^1]+=tmp; nowflow-=tmp; mincost+=tmp*w[k]; sum+=tmp; } } return sum; } int main() { memset(fir,-1,sizeof(fir)); N=read(); for(ll i=1;i<=N;i++) { ll r=read(); addedge(i,N*2+1,r,0); addedge(0,i+N,r,0); } p=read(),m=read(),f=read(),n=read(),s=read(); for(ll i=1;i<=N;i++) { addedge(0,i,inf,p); if(i+m<=N)addedge(i+N,i+m,inf,f); if(i+n<=N)addedge(i+N,i+n,inf,s); if(i+1<=N)addedge(i,i+1,inf,0); } while(spfa()!=-1) { memset(vis,0,sizeof(vis)); getfl(0,0x7fffffff); } cout<<mincost; return 0; }
View Code

並不對勁的餐巾計劃問題