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


    题目描述

    一个餐厅在相继的 NN 天里,每天需用的餐巾数不尽相同。假设第 ii 天需要 r_iri块餐巾( i=1,2,...,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 pp 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 nn天(n>mn>m),其费用为 ss 分(s<fs<f)。

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

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

    输入输出格式

    输入格式:

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

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

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

    输出格式

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

    解题思路:

    考虑一下流量问题,发现最大流已经确定了。

    此时需要构造一个流使每天的流量都满足要求,

    那么就应该在汇点附近约束。

    所以需要让每天的餐巾指向汇点。

    需要满足直接购买,所以连入新流通入餐巾流中。

    考虑餐巾的来源还有洗,那么在前几天的废餐巾指向这个新餐巾。

    而废餐巾每天的数量都是固定的,所以连源上就好了。

    考虑到可能有余负,向下一天的餐巾连边

    建图都讲了边权就不说了。

    最后跑一遍费用流就好了。

    代码:

      1 #include<queue>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 typedef long long lnt;
      6 const lnt oo=0x3f3f3f3f3f3f3f3fll;
      7 struct pnt{
      8     int hd;
      9     int pre;
     10     int lst;
     11     lnt val;
     12     lnt dis;
     13     bool vis;
     14 }p[1000000];
     15 struct ent{
     16     int twd;
     17     int lst;
     18     lnt vls;
     19     lnt dis;
     20 }e[1000000];
     21 int cnt;
     22 int n,m;
     23 int s,t;
     24 int P,M,F,N,S;
     25 std::queue<int>Q;
     26 void ade(int f,int t,lnt v,lnt d)
     27 {
     28     cnt++;
     29     e[cnt].twd=t;
     30     e[cnt].vls=v;
     31     e[cnt].dis=d;
     32     e[cnt].lst=p[f].hd;
     33     p[f].hd=cnt;
     34     return ;
     35 }
     36 bool Spfa(void)
     37 {
     38     while(!Q.empty())Q.pop();
     39     for(int i=1;i<=t;i++)
     40     {
     41         p[i].dis=p[i].val=oo;
     42         p[i].vis=false;
     43     }
     44     p[s].dis=0;
     45     p[s].vis=true;
     46     p[t].pre=-1;
     47     Q.push(s);
     48     while(!Q.empty())
     49     {
     50         int x=Q.front();
     51         Q.pop();
     52         p[x].vis=false;
     53         for(int i=p[x].hd;i;i=e[i].lst)
     54         {
     55             int to=e[i].twd;
     56             if(p[to].dis>p[x].dis+e[i].dis&&e[i].vls>0)
     57             {
     58                 p[to].dis=p[x].dis+e[i].dis;
     59                 p[to].pre=x;
     60                 p[to].val=std::min(p[x].val,e[i].vls);
     61                 p[to].lst=i;
     62                 if(p[to].vis)continue;
     63                 p[to].vis=true;
     64                 Q.push(to);
     65             }
     66         }
     67     }
     68     return p[t].pre!=-1;
     69 }
     70 lnt Ek(void)
     71 {
     72     lnt ans=0;
     73     while(Spfa())
     74     {
     75         ans+=p[t].dis*p[t].val;
     76         for(int i=t;i!=s;i=p[i].pre)
     77         {
     78             e[p[i].lst].vls-=p[t].val;
     79             e[((p[i].lst-1)^1)+1].vls+=p[t].val;
     80         }
     81     }
     82     return ans;
     83 }
     84 int main()
     85 {
     86 //    freopen("a.in","r",stdin);
     87     scanf("%d",&n);
     88     s=n*2+1;
     89     t=s+1;
     90     for(int i=1;i<=n;i++)
     91     {
     92         int v;
     93         scanf("%d",&v);
     94         ade(i,t,v,0);
     95         ade(t,i,0,0);
     96         ade(s,i+n,v,0);
     97         ade(i+n,s,0,0);
     98     }
     99     scanf("%d%d%d%d%d",&P,&M,&F,&N,&S);
    100     for(int i=1;i<=n;i++)
    101     {
    102         ade(s,i,oo,P);
    103         ade(i,s,0,-P);
    104         if(i+M<=n)
    105         {
    106             ade(i+n,i+M,oo,F);
    107             ade(i+M,i+n,0,-F);
    108         }
    109         if(i+N<=n)
    110         {
    111             ade(i+n,i+N,oo,S);
    112             ade(i+N,i+n,0,-S);
    113         }
    114         if(i+1<=n)
    115         {
    116             ade(i,i+1,oo,0);
    117             ade(i+1,i,0,0);
    118         }
    119     }
    120     printf("%lld
    ",Ek());
    121     return 0;
    122 }
  • 相关阅读:
    原来是板子的硬件问题
    最简单的helloworld模块编译加载(linux3.5内核源码树建立)
    排序学习笔记
    配置开发环境遇到的一些问题及解决方法
    .NET基础之GridView控件
    .NET之页面数据缓存
    .NET基础之Calendar控件
    【转帖】DIV+CSS完美兼容IE6/IE7/FF的通用方法
    ADO.NET()Command
    .NET基础之DataList控件
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10210775.html
Copyright © 2020-2023  润新知