• 餐巾计划问题(费用流)


    餐巾计划问题

    https://www.luogu.org/problemnew/show/P1251

    题目描述

    一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同。假设第 i 天需要 ri块餐巾( i=1,2,...,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,

    洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s 分(s<f)。

    每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。

    试设计一个算法为餐厅合理地安排好 N 天中餐巾使用计划,使总的花费最小。编程找出一个最佳餐巾使用计划。

    输入输出格式

    输入格式:

    由标准输入提供输入数据。文件第 1 行有 1 个正整数 N,代表要安排餐巾使用计划的天数。

    接下来的 N 行是餐厅在相继的 N 天里,每天需用的餐巾数。

    最后一行包含5个正整数p,m,f,n,s。p 是每块新餐巾的费用; m 是快洗部洗一块餐巾需用天数; f 是快洗部洗一块餐巾需要的费用; n 是慢洗部洗一块餐巾需用天数; s 是慢洗部洗一块餐巾需要的费用。

    输出格式:

    将餐厅在相继的 N 天里使用餐巾的最小总花费输出

    输入输出样例

    输入样例#1: 
    3
    1 7 5 
    11 2 2 3 1
    
    输出样例#1: 
    134
    

    说明

    N<=2000

    ri<=10000000

    p,f,s<=10000

    时限4s

    参考博客:https://www.luogu.org/blog/user31955/solution-p1251

    注意开long long

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<queue>
      4 #include<cstring>
      5 using namespace std;
      6 
      7 const int INF=0x3f3f3f3f;
      8 const int N=500005;
      9 const int M=500005;
     10 int top;
     11 long long dist[N];
     12 int pre[N];
     13 bool vis[N];
     14 int c[N];
     15 int maxflow;
     16 
     17 struct Vertex{
     18     int first;
     19 }V[N];
     20 struct Edge{
     21     int v,next;
     22     int cap,flow,cost;
     23 }E[M];
     24 
     25 void init(){
     26     memset(V,-1,sizeof(V));
     27     top=0;
     28     maxflow=0;
     29 }
     30 
     31 void add_edge(int u,int v,int c,int cost){
     32     E[top].v=v;
     33     E[top].cap=c;
     34     E[top].flow=0;
     35     E[top].cost=cost;
     36     E[top].next=V[u].first;
     37     V[u].first=top++;
     38 }
     39 
     40 void add(int u,int v,int c,int cost){
     41     add_edge(u,v,c,cost);
     42     add_edge(v,u,0,-cost);
     43 }
     44 
     45 bool SPFA(int s,int t,int n){
     46     int i,u,v;
     47     queue<int>qu;
     48     memset(vis,false,sizeof(vis));
     49     memset(c,0,sizeof(c));
     50     memset(pre,-1,sizeof(pre));
     51     for(i=1;i<=n;i++){
     52         dist[i]=0x3f3f3f3f3f3f3f3f;
     53     }
     54     vis[s]=true;
     55     c[s]++;
     56     dist[s]=0;
     57     qu.push(s);
     58     while(!qu.empty()){
     59         u=qu.front();
     60         qu.pop();
     61         vis[u]=false;
     62         for(i=V[u].first;~i;i=E[i].next){
     63             v=E[i].v;
     64             if(E[i].cap>E[i].flow&&dist[v]>dist[u]+E[i].cost){
     65                 dist[v]=dist[u]+E[i].cost;
     66                 pre[v]=i;
     67                 if(!vis[v]){
     68                     c[v]++;
     69                     qu.push(v);
     70                     vis[v]=true;
     71                     if(c[v]>n){
     72                         return false;
     73                     }
     74                 }
     75             }
     76         }
     77     }
     78     if(dist[t]==0x3f3f3f3f3f3f3f3f){
     79         return false;
     80     }
     81     return true;
     82 }
     83 
     84 long long MCMF(int s,int t,int n){
     85     int d;
     86     int i;
     87     long long mincost;
     88     mincost=0;
     89     while(SPFA(s,t,n)){
     90         d=INF;
     91         for(i=pre[t];~i;i=pre[E[i^1].v]){
     92             d=min(d,E[i].cap-E[i].flow);
     93         }
     94         maxflow+=d;
     95         for(i=pre[t];~i;i=pre[E[i^1].v]){
     96             E[i].flow+=d;
     97             E[i^1].flow-=d;
     98         }
     99         mincost+=dist[t]*d;
    100        // cout<<d<<endl;
    101     }
    102     return mincost;
    103 }
    104 
    105 
    106 
    107 int main(){
    108     int n,m;
    109     int v,u,w,c;
    110     int s,t;
    111     cin>>n;
    112     init();
    113     s=0,t=n+n+1;
    114     for(int i=1;i<=n;i++){
    115         cin>>w;
    116         add(s,i,w,0);//每天晚上从起点获得x条脏餐巾
    117         add(n+i,t,w,0);//每天白天,向汇点提供x条干净的餐巾,流满时表示第i天的餐巾够用
    118     }
    119     int P,t1,t2,cost1,cost2;
    120     cin>>P>>t1>>cost1>>t2>>cost2;
    121     for(int i=1;i<=n;i++){
    122         add(s,i+n,INF,P);//每天早上可以购买餐巾
    123         if(i+1<=n) add(i,i+1,INF,0);//每天晚上可以将脏餐巾留到第二天晚上
    124         if(i+t1<=n) add(i,i+n+t1,INF,cost1);//每天晚上可以送去快洗部,在地i+t1天早上收到餐巾
    125         if(i+t2<=n) add(i,i+n+t2,INF,cost2);//每天晚上可以送去慢洗部,在地i+t2天早上收到餐巾
    126     }
    127     long long ans=MCMF(s,t,n+n+2);
    128     cout<<ans<<endl;
    129 }
    View Code
  • 相关阅读:
    c# winform 应用编程代码总结 5
    c# winform 应用编程代码总结 6
    C语言 如何隐藏DOS窗口
    c# winform 应用编程代码总结 13
    c# winform 应用编程代码总结 8
    c# winform 应用编程代码总结 7
    c# winform 应用编程代码总结 10
    Ext grid改变行背景颜色 和改变行字体颜色
    我的博客学习记录一箩筐(每天更新)
    New version of wxDesigner based on wxWidgets pre3.0 released
  • 原文地址:https://www.cnblogs.com/Fighting-sh/p/9848890.html
Copyright © 2020-2023  润新知