zoukankan      html  css  js  c++  java
  • BZOJ 2424: [HAOI2010]订货

    2424: [HAOI2010]订货

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 915  Solved: 639
    [Submit][Status][Discuss]

    Description

    某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费。假设仓库容量为S。

    Input

    第1行:n, m, S (0<=n<=50, 0<=m<=10, 0<=S<=10000)
    第2行:U1 , U2 , ... , Ui , ... , Un (0<=Ui<=10000)
    第3行:d1 , d2 , ..., di , ... , dn (0<=di<=100)

    Output

    只有1行,一个整数,代表最低成本

    Sample Input

    3 1 1000
    2 4 8
    1 2 4

    Sample Output

    34

    HINT

     

    Source

    [Submit][Status][Discuss]

    动态规划。

    一开始看到题面的时候以为是那道经典的贪心问题,就是维护当前最优单价,不断转移。

    然而这道题限制了仓库的容量,使得最优单价不能直接向后转移,所以需要动态规划。

    设$f[i][j]$表示经过了第$i$个月(此时已经到了月底),仓库中剩余量为$j$的当前最小费用。

    转移如下:

    $f[i][j+1]=min(f[i][j+1],f[i][j]+D_{i})$ 表示可以在本月额外购进一单位作为储存。

    当$j geq U_{i+1}$, $f[i+1][j-U_{i+1}]=min(f[i+1][j-U_{i+1}],f[i][j]+M*j$ 表示如果当前储备够下个月出售,下个月可以不购进商品,只需支付两个月之间的储存费用。

    当$j lt U_{i+1}$, $f[i+1][0]=min(f[i+1][0],f[i][j]+M*j+(U_{i+1}-j)*D_{i+1}$ 表示如果当前储备不够下个月,下个月除了需要支付储存费用,还需要额外购进一些商品。

     1 #include <cstdio>
     2 
     3 inline int nextChar(void)
     4 {
     5     const static int siz = 1024;
     6     
     7     static char buf[siz];
     8     static char *hd = buf + siz;
     9     static char *tl = buf + siz;
    10     
    11     if (hd == tl)
    12         fread(hd = buf, 1, siz, stdin);
    13         
    14     return *hd++;
    15 }
    16 
    17 inline int nextInt(void)
    18 {
    19     register int ret = 0;
    20     register int neg = false;
    21     register int bit = nextChar();
    22     
    23     for (; bit < 48; bit = nextChar())
    24         if (bit == '-')neg ^= true;
    25         
    26     for (; bit > 47; bit = nextChar())
    27         ret = ret * 10 + bit - 48;
    28         
    29     return neg ? -ret : ret;
    30 }
    31 
    32 const int inf = 1e9;
    33 const int maxn = 55;
    34 const int maxm = 10005;
    35 
    36 int N, M, S;
    37 int U[maxn];
    38 int D[maxn];
    39 
    40 int f[maxn][maxm];
    41 
    42 inline void Min(int &a, const int &b)
    43 {
    44     if (a > b)a = b;
    45 }
    46 
    47 signed main(void)
    48 {
    49     N = nextInt();
    50     M = nextInt();
    51     S = nextInt();
    52     
    53     for (int i = 1; i <= N; ++i)
    54         U[i] = nextInt();
    55         
    56     for (int i = 1; i <= N; ++i)
    57         D[i] = nextInt();
    58         
    59     for (int i = 0; i <= N; ++i)
    60         for (int j = 0; j <= S; ++j)
    61             f[i][j] = inf;
    62             
    63     f[1][0] = D[1] * U[1];
    64     
    65     for (int i = 0; i <= N; ++i)
    66         for (int j = 0; j <= S; ++j)
    67             if (f[i][j] < inf)
    68             {
    69                 Min(f[i][j + 1], f[i][j] + D[i]);
    70                 if (j >= U[i + 1])
    71                     Min(f[i + 1][j - U[i + 1]], f[i][j] + j * M);
    72                 else
    73                     Min(f[i + 1][0], f[i][j] + (U[i + 1] - j) * D[i + 1] + j * M);
    74             }
    75             
    76     int ans = inf;
    77     
    78     for (int i = 0; i <= S; ++i)
    79         Min(ans, f[N][i]);
    80         
    81     printf("%d
    ", ans);
    82 }
    83  

    突然,机房小伙伴们惊奇地看我:“这特么不是裸的费用流吗?”

    WOC,我是有多蠢,去想DP?LTY神犇要来HACK我了,好怕怕~~~

    补上最小费用流代码……

      1 #include <cstdio>
      2 #include <cstring>
      3 
      4 inline char nextChar(void)
      5 {
      6     static const int siz = 1024;
      7     
      8     static char buf[siz];
      9     static char *hd = buf + siz;
     10     static char *tl = buf + siz;
     11     
     12     if (hd == tl)
     13         fread(hd = buf, 1, siz, stdin);
     14     
     15     return *hd++;
     16 }
     17 
     18 inline int nextInt(void)
     19 {
     20     register int ret = 0;
     21     register int neg = false;
     22     register int bit = nextChar();
     23     
     24     for (; bit < 48; bit = nextChar())
     25         if (bit == '-')neg ^= true;
     26     
     27     for (; bit > 47; bit = nextChar())
     28         ret = ret * 10 + bit - 48;
     29         
     30     return neg ? -ret : ret;
     31 }
     32 
     33 const int siz = 50005;
     34 const int inf = 1000000007;
     35 
     36 int tot;
     37 int s, t;
     38 int hd[siz];
     39 int to[siz];
     40 int fl[siz];
     41 int vl[siz];
     42 int nt[siz];
     43 
     44 inline void add(int u, int v, int f, int w)
     45 {
     46     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; vl[tot] = +w; hd[u] = tot++;
     47     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; vl[tot] = -w; hd[v] = tot++;
     48 }
     49 
     50 int dis[siz];
     51 int pre[siz];
     52 
     53 inline bool spfa(void)
     54 {
     55     static int que[siz];
     56     static int inq[siz];
     57     static int head, tail;
     58     
     59     memset(dis, 0x3f, sizeof(dis));
     60     memset(inq, 0, sizeof(inq));
     61     head = 0, tail = 0;
     62     que[tail++] = s;
     63     pre[s] = -1;
     64     dis[s] = 0;
     65     inq[s] = 1;
     66     
     67     while (head != tail)
     68     {
     69         int u = que[head++], v; inq[u] = 0;
     70         
     71         for (int i = hd[u]; ~i; i = nt[i])
     72             if (dis[v = to[i]] > dis[u] + vl[i] && fl[i])
     73             {
     74                 dis[v] = dis[u] + vl[i], pre[v] = i ^ 1;
     75                 if (!inq[v])inq[que[tail++] = v] = 1;
     76             }
     77     }
     78     
     79     return dis[t] < 0x3f3f3f3f;
     80 }
     81 
     82 inline int minCost(void)
     83 {
     84     int cost = 0, flow;
     85     
     86     while (spfa())
     87     {
     88         flow = inf;
     89         
     90         for (int i = pre[t]; ~i; i = pre[to[i]])
     91             if (flow > fl[i ^ 1])flow = fl[i ^ 1];
     92         
     93         for (int i = pre[t]; ~i; i = pre[to[i]])
     94             fl[i] += flow, fl[i ^ 1] -= flow;
     95             
     96         cost += dis[t] * flow;
     97     }
     98     
     99     return cost;
    100 }
    101 
    102 int n, m, k;
    103 
    104 signed main(void)
    105 {
    106     n = nextInt();
    107     m = nextInt();
    108     k = nextInt();
    109     
    110     s = 0, t = n + 1;
    111     
    112     memset(hd, -1, sizeof(hd));
    113     
    114     for (int i = 1; i <= n; ++i)
    115         add(i, t, nextInt(), 0);
    116         
    117     for (int i = 1; i <= n; ++i)
    118         add(s, i, inf, nextInt());
    119         
    120     for (int i = 1; i < n; ++i)
    121         add(i, i + 1, k, m);
    122         
    123     printf("%d
    ", minCost());
    124 }

    @Author: YouSiki

  • 相关阅读:
    C# 使用 Microsoft.Feeds 组件获取 RSS 全文
    使用 Jquery 做类似搜索引擎效果
    ASP.NET MVC 利用 IHttpModule 实现路由调试
    Python 爬虫类库 Selenium 的常用方法介绍
    C# 中 New 关键词的几种用法
    ASP.NET 使用 IIS URL Rewrite 模块实现伪静态
    Java 源码分析之 HashTable
    Java 类中代码块和构造方法的执行顺序
    C# 中使用 FFmpeg.NET
    C# 项目中使用 ServiceStack.Redis 操作 Redis
  • 原文地址:https://www.cnblogs.com/yousiki/p/6254933.html
Copyright © 2011-2022 走看看