当前位置: 首页 > news >正文

【BZOJ】2879: [Noi2012]美食节

题意

\(m\)个厨师,\(n\)种菜,每种菜需要做\(p_i\)份,每个厨师做第\(i\)种菜用时\(t_{i, j}\)。一个厨师做完一道菜才能做下一道。每份菜的时间是这个厨师做完这道菜的用时加上之前做过的菜的用时。问做完所有的菜的最小用时是多少。($ n \le 40, m \le 100, \sum p_i \le 800, t_{i, j} \le 1000 $)

分析

可以考虑每个厨师做的每一道菜。最后做的菜对时间贡献了一次,倒数第二的菜对时间贡献了两次。于是我们考虑每个厨师倒着做的菜品即可。

题解

将每个厨师拆成\(\sum p_i\)个点,表示这个菜是倒数第\(i\)次做的。但是这样一次性把图建出来会tle。所以我们要优化。
考虑到每个厨师倒数第一个菜一定在倒数第二个菜先做,所以我们按照这个顺序来建图即可,即增广一次建一次。
具体做法是:
首先加入\(m\)个点,表示每个厨师倒数第一次做的菜。源\(S\)向这些点连边,容量\(1\),费用为\(0\)。再加入\(n\)个点,表示菜类,每个点向汇连边,容量为\(p_i\),费用为\(0\)。然后在厨师的点集中向菜类点集连边,容量为\(1\),费用为\(t_{i, j}\)
然后增广一条路径。此时找出被增广的厨师,再新建一个点,表示这个厨师第二次做的菜。源\(S\)向这个点连边,容量为\(1\),费用为\(0\)。然后向菜类连边,容量为\(1\),费用为\(2 t_{i, j}\)。依次类推。

#include <bits/stdc++.h>
using namespace std;
const int N=45, M=105, nN=N+M+1000, nE=N*(M+800)*8, oo=0x3f3f3f3f;
int ihead[nN], cnt=1;
struct E {
    int next, from, to, cap, w;
}e[nE];
void add(int x, int y, int cap, int w) {
    e[++cnt]=(E){ihead[x], x, y, cap, w}; ihead[x]=cnt;
    e[++cnt]=(E){ihead[y], y, x, 0,  -w}; ihead[y]=cnt;
}
bool spfa(int s, int t, int n, int &ans) {
    static int d[nN], q[nN], p[nN], fr, ta;
    static bool vis[nN];
    memset(d, 0x3f, sizeof(int)*(n+1));
    fr=ta=0;
    d[s]=0;
    q[ta++]=s;
    while(fr!=ta) {
        int x=q[fr++];
        fr=fr==nN?0:fr;
        vis[x]=0;
        for(int i=ihead[x]; i; i=e[i].next) {
            if(!e[i].cap) {
                continue;
            }
            int y=e[i].to;
            if(d[y]>d[x]+e[i].w) {
                d[y]=d[x]+e[i].w;
                p[y]=i;
                if(!vis[y]) {
                    vis[y]=1;
                    q[ta++]=y;
                    ta=ta==nN?0:ta;
                }
            }
        }
    }
    if(d[t]==oo) {
        return 0;
    }
    for(int x=t; x!=s; x=e[p[x]].from) e[p[x]].cap--, e[p[x]^1].cap++;
    ans+=d[t];
    return 1;
}
int n, m, p[N], sum, pos[M], num[M], t[N][M], nu[N];
int main() {
    int ans=0;
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; ++i) {
        scanf("%d", &p[i]);
        sum+=p[i];
    }
    int S=n+m+sum+1, T=S+1;
    for(int i=1; i<=n; ++i) {
        add(S, i, p[i], 0);
        for(int j=1; j<=m; ++j) {
            scanf("%d", &t[i][j]);
        }
    }
    for(int j=1; j<=m; ++j) {
        int id=n+j;
        add(id, T, 1, 0);
        num[j]=1;
        pos[j]=cnt;
        for(int i=1; i<=n; ++i) {
            add(i, id, 1, t[i][j]);
        }
    }
    int tot=n+m;
    while(spfa(S, T, T, ans)) {
        int j=0;
        for(j=1; j<=m && !e[pos[j]].cap; ++j);
        ++num[j];
        ++tot;
        add(tot, T, 1, 0);
        pos[j]=cnt;
        for(int i=1; i<=n; ++i) {
            add(i, tot, 1, num[j]*t[i][j]);
        }
    }
    printf("%d\n", ans);
    return 0;
}

相关文章:

  • gulp 教程
  • 虚拟化之vmx配置文件
  • 致北京
  • 二进制方式快速安装MySQL数据库
  • 沙盒 文件操作
  • PHP上传(单个)文件示例
  • UESTC 1246 拆x3
  • 积分显示算法(4.34.5 4.14 4.65)
  • linux中ssh免密码登录
  • postgresql cluster和correlation
  • 有限概率(拉普拉斯概率)
  • Android Stduio统计项目的代码行数
  • struts2获取web元素(request、session、application)
  • DVWA系列之4 利用SQLMap进行medium级别注入
  • Filter 过滤器
  • JavaScript 如何正确处理 Unicode 编码问题!
  • [nginx文档翻译系列] 控制nginx
  • Hexo+码云+git快速搭建免费的静态Blog
  • input的行数自动增减
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • JavaScript新鲜事·第5期
  • java小心机(3)| 浅析finalize()
  • JS数组方法汇总
  • React Native移动开发实战-3-实现页面间的数据传递
  • Redis字符串类型内部编码剖析
  • ucore操作系统实验笔记 - 重新理解中断
  • 大整数乘法-表格法
  • 关于Flux,Vuex,Redux的思考
  • 利用jquery编写加法运算验证码
  • 前端存储 - localStorage
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 深度学习入门:10门免费线上课程推荐
  • 使用Swoole加速Laravel(正式环境中)
  • 手写一个CommonJS打包工具(一)
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • ​configparser --- 配置文件解析器​
  • $GOPATH/go.mod exists but should not goland
  • (1)常见O(n^2)排序算法解析
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (Java数据结构)ArrayList
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (差分)胡桃爱原石
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (三分钟)速览传统边缘检测算子
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (转载)PyTorch代码规范最佳实践和样式指南
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .Net FrameWork总结
  • .NET实现之(自动更新)
  • .pings勒索病毒的威胁:如何应对.pings勒索病毒的突袭?
  • [<死锁专题>]