队列斜率优化的dp问题。
#include<iostream> #include<string> #include<queue> #include<vector> #include<cstdio> #include<cstring> using namespace std; typedef pair<int,int> pii; priority_queue<pii>q; int n,m; int num[10000000]; int f[200][10005]; int u[500];//需求; int d[500];//费用; int qq[200][10005]; int head[2000],tail[2000]; int main() { int n,m,s;//m每月费用 scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=n;i++) scanf("%d",&u[i]); for(int i=1;i<=n;i++) scanf("%d",&d[i]); qq[0][0]=0; qq[0][1]=0; memset(f,10,sizeof(f)); f[0][0]=0; for(int i=1;i<=n;i++)head[i]=1; for(int i=1;i<=n;i++) for(int j=s;j>=0;j--) { while(qq[i-1][head[i-1]]>j+u[i]&&head[i-1]<tail[i-1]) head[i-1]++; int k=qq[i-1][head[i-1]]; f[i][j]=f[i-1][k]+(j+u[i]-k)*d[i]+m*k; while(f[i][j]+(m-d[i+1])*j<=f[i][qq[i][tail[i]]]+(m-d[i+1])*qq[i][tail[i]]&&head[i]<=tail[i])tail[i]--; qq[i][++tail[i]]=j; } cout<<f[n][0]<<endl; return 0; }
真:费用流版:
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define maxx 200000
using namespace std;
int read()
{
int k;
cin>>k;
return k;
}
struct
{
int y,next,flow;
int v;
}e[100000];
int ans=0;
int len=0;
int lin[1000000];
int re[10000000];
int init(int x,int y,int v,int flow)
{
e[++len].y=y;
e[len].next=lin[x];
e[len].flow=flow;
e[len].v=v;
re[len]=len+1;
lin[x]=len;
e[++len].y=x;
e[len].next=lin[y];
e[len].v=-v;
e[len].flow=0;
re[len]=len-1;
lin[y]=len;
return 0;
}
int n,m,s;
int tot=0;
int map[10000000];
int map1[1000000];
int map2[1000000];
int map3[1000000];
int st,ed;
int a[10000000];
int b[10000000];
void initx()
{
/*
map1 进货;
map2 出货;
map 辅助点1;
map3 复制点 2
*/
n=read();
m=read();
s=read();
st=++tot;
for(int i=1;i<=n;i++){map1[i]=++tot;}
for(int i=1;i<=n;i++){map2[i]=++tot;map[i]=++tot;}
for(int i=1;i<=n;i++)map3[i]=++tot;
for(int i=1;i<=n;i++){a[i]=read();}
for(int i=1;i<=n;i++)b[i]=read();
ed=++tot;
for(int i=1;i<=n;i++)
{
init(st,map1[i],b[i],maxx);
init(map1[i],map2[i],0,maxx);
init(map2[i],ed,0,a[i]);
}
for(int i=1;i<=n-1;i++)
{
init(map1[i],map[i],0,s);
init(map[i],map3[i],m,s);
init(map3[i],map2[i+1],0,s);
if(i+1<=n-1)
init(map3[i],map[i+1],0,s);
}
return ;
}
int q[10000];
int dis[100000];
int vis[100000];
int lastvis[100000];
int lastlen[100000];
int head=0,tail=1;
bool spfa()
{
//cout<<"-----------------------------------"<<endl;
memset(vis,0,sizeof(vis));
memset(dis,10,sizeof(dis));
head=0;tail=1;
vis[st]=1;
q[1]=st;
dis[st]=0;
while(head++<tail)
{
int x=q[head];
/* cout<<"the head it "<<x<<endl;
cout<<"::::::::::::::"<<lin[x]<<"---"<<e[lin[x]].flow<<"++"<<e[lin[x]].y<<endl;
*/vis[x]=0;
for(int i=lin[x];i;i=e[i].next)
{
if(e[i].flow<=0)continue;
int y=e[i].y;
if(dis[x]+e[i].v<dis[y])
{
// cout<<"the new y is "<<y<<endl;
dis[y]=dis[x]+e[i].v;
if(vis[y]==0)q[++tail]=y,vis[y]=1;
lastvis[y]=x;lastlen[y]=i;
}
//else cout<<"the wrong y is"<<y<<endl;
// cout<<"k";
}
}
return dis[ed]!=dis[0];
}
int agu()
{
int dalet=dis[0];
for(int now=ed;now!=st;now=lastvis[now])
{
dalet=min(e[lastlen[now]].flow,dalet);
}
for(int now=ed;now!=st;now=lastvis[now])
{
// cout<<now<<endl;
e[lastlen[now]].flow-=dalet;
e[re[lastlen[now]]].flow+=dalet;
ans+=dalet*e[lastlen[now]].v;
}
}
void costflow()
{
while(spfa())
agu();
cout<<ans<<endl;
}
int main()
{
initx();
costflow();
return 0;
}