##题目大意:
有n个月,第i个月需要ui件货物,每个单位的货物再第i个月的价格是di,仓库容量为s,每放在仓库贮存1个月,每个单位的货物就要使用m元,若当月卖了出去则不用付.
##解题思路:
赤裸裸的费用流
其实网络流最重要的就是建图
图建好了套模版
下面是建图方式:
1.建立源点与每个月连接,流量为无穷大,费用为di.
2.建立汇点与每个月连接,流量为ui,费用为0.
3.第i个月与第i+1个月连接,流量为s,费用为m.
原因:
1.可以买进无数件,费用当然就是价格
2.最大流,这ui肯定要流的,然后费用在源点与每个月之间就已经"买单"了.
3.仓库容量是s,费用是m,然后货物可以给下个月用
##源程序:
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
struct node{
int x,to,f,c,next;
}e[205];
int d[55],pre[55],last[55],cnt=-1,ans,n,m,S,s,t;
bool v[55];
void add(int u,int v,int c,int w)
{
e[++cnt].x=u;e[cnt].to=v;e[cnt].f=w;e[cnt].c=c;e[cnt].next=last[u];last[u]=cnt;
e[++cnt].x=v;e[cnt].to=u;e[cnt].f=-w;e[cnt].c=0;e[cnt].next=last[v];last[v]=cnt;
}
bool spfa()
{
queue<int> q;
for (int i=s;i<=t;i++) d[i]=1e9;
memset(pre,-1,sizeof(pre));
memset(v,0,sizeof(v));
d[s]=0;q.push(s);v[s]=1;
while(q.size())
{
int u=q.front();q.pop();v[u]=0;
for (int i=last[u];~i;i=e[i].next)
if (e[i].c&&d[e[i].to]>d[u]+e[i].f)
{
d[e[i].to]=d[u]+e[i].f;
pre[e[i].to]=i;
if (!v[e[i].to])
{
v[e[i].to]=1;
q.push(e[i].to);
}
}
}
return d[t]!=1e9;
}
void mcf()
{
int i=t,minn=1e9;
while (~pre[i])
{
minn=min(e[pre[i]].c,minn);
i=e[pre[i]].x;
}
ans+=d[t]*minn; i=t;
while (~pre[i])
{
e[pre[i]].c-=minn;
e[pre[i]^1].c+=minn;
i=e[pre[i]].x;
}
return;
}
int spf()
{
while (spfa())
mcf();
return ans;
}
//上面的都是模版
//我就不解释了
int main()
{
memset(last,-1,sizeof(last));//初始化
scanf("%d%d%d",&n,&m,&S);
s=0;t=n+1;//建立源点汇点
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
add(i,t,x,0);//连接(每个月与汇点)
}
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
add(s,i,1e9,x);//连接(源点与每个月)
}
for (int i=1;i<n;i++) add(i,i+1,S,m);//连接(每个月之间)
//这里要i不能等于n,如果等于n,最后一个月就会和汇点再连一条线
//就会改变整个费用流的结果
printf("%d",spf());
}