洛谷1251餐巾紙問題
阿新 • • 發佈:2017-12-01
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餐巾紙問題