zoukankan      html  css  js  c++  java
  • [网络流24题]餐巾计划问题

    题目:洛谷P1251。

    题目大意:
    一个餐厅N天,每天需要ri块餐巾。每块餐巾需要p元,每天用过的餐巾变脏,不能直接用。现在有快洗店和慢洗店,快洗店洗餐巾需要m天,每块花费f元;慢洗店洗餐巾需要n天,每块餐巾s元(m < n,s<  f)。现要求最新的花费使满足每天所需。
    解题思路:
    最小费用最大流建模。
    把每天拆成白天和晚上(白天产生脏餐巾,晚上得到干净餐巾)。
    从S向每个白天连容量ri,费用0的边;从每个晚上向T连容量ri,费用0的边。代表每天所需的餐巾数。
    从第i天的白天向第i+m天的晚上连容量无穷,费用f的边。(快洗)
    从第i天的白天向第i+n天的晚上连容量无穷,费用s的边。(慢洗)
    从S向每天晚上连容量无穷,费用p的边,代表直接买干净的餐巾。
    从第i天晚上向第i+1天晚上连容量无穷,费用0的边,代表干净餐巾可以留到下一天。
    跑费用流即可。

    C++ Code:

    #include<bits/stdc++.h>
    using namespace std;
    #define T 7000
    #define N 7005
    #define LoveLive long long
    #define inf 0x3f3f3f3f
    int n,p,m,f,nn,s,h[2005];
    inline int readint(){
    	int c=getchar(),d=0;
    	for(;!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    	return d;
    }
    struct Graph{
    	std::queue<int>q;
    	int head[N],cnt,pre_e[N],a[N];
    	LoveLive d[N];
    	bool vis[N];
    	struct edge{
    		int from,to,cap,cost,nxt;
    	}e[1000005];
    	inline void addedge(const int u,const int v,const int flow,const int cost){
    		e[++cnt]=(edge){u,v,flow,cost,head[u]};
    		head[u]=cnt;
    		e[++cnt]=(edge){v,u,0,-cost,head[v]};
    		head[v]=cnt;
    	}
    	Graph():cnt(1){
    		memset(head,-1,sizeof head);
    	}
    	bool bfs(LoveLive& flow,LoveLive& cost){
    		memset(d,0x3f,sizeof d);
    		memset(a,0x3f,sizeof a);
    		memset(vis,0,sizeof vis);
    		memset(pre_e,0,sizeof pre_e);
    		d[0]=0;
    		vis[0]=1;
    		q.push(0);
    		while(!q.empty()){
    			int u=q.front();q.pop();
    			vis[u]=0;
    			for(int i=head[u];~i;i=e[i].nxt)
    			if(e[i].cap&&d[e[i].to]>d[u]+e[i].cost){
    				d[e[i].to]=d[u]+e[i].cost;
    				a[e[i].to]=min(a[u],e[i].cap);
    				pre_e[e[i].to]=i;
    				if(!vis[e[i].to]){
    					vis[e[i].to]=1;
    					q.push(e[i].to);
    				}
    			}
    		}
    		if(d[T]>100000000000000000)return 0;
    		flow+=a[T];
    		cost+=d[T]*a[T];
    		for(int i=T;i;i=e[pre_e[i]].from){
    			e[pre_e[i]].cap-=a[T];
    			e[pre_e[i]^1].cap+=a[T];
    		}
    		return 1;
    	}
    	LoveLive ek(){
    		LoveLive flow=0,cost=0;
    		while(bfs(flow,cost));
    		return cost;
    	}
    }g;
    int main(){
    	n=readint();
    	for(int i=1;i<=n;++i)h[i]=readint();
    	p=readint(),m=readint(),f=readint(),nn=readint(),s=readint();
    	for(int i=1;i<=n;++i){
    		g.addedge(0,i,h[i],0);
    		g.addedge(i+n,T,h[i],0);
    		if(i+m<=n)g.addedge(i,i+n+m,inf,f);
    		if(i+nn<=n)g.addedge(i,i+n+nn,inf,s);
    		g.addedge(0,i+n,inf,p);
    		if(i!=n)g.addedge(i,i+1,inf,0);
    	}
    	cout<<g.ek()<<endl;
    	return 0;
    }
    
  • 相关阅读:
    正则表达式数据验证
    .NET开发工具
    (收藏)自己觉得好的学习网站 持续更新... ...
    MSSQL获取表结构通用方法
    第一阶段冲刺个人博客07
    第一阶段冲刺个人博客06
    第8周学习进度
    第一阶段冲刺个人博客05
    ”图书馆助手“典型用户和用户场景
    ”图书馆助手“典型用户和用户场景
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9130400.html
Copyright © 2011-2022 走看看