dpHA省选【斜率优化dp】

队列斜率优化的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;
}

  

原文地址:https://www.cnblogs.com/Lazers/p/6560566.html