题目

题目大意

工厂内每个人只会操作一些机器。

他们会以随机的顺序来,每次选任意一台机器来操作。

一台机器只能由一个工人来操作。

可以花费一的代价来使某个工人学会一种机器。

问花费最少的代价,使得在所有的情况下每个人都能操纵一台机器。


正解

这题可以转化成个二分图。而答案一定满足:所有联通块都是个完全二分图。

我们要用最少的代价来造出这样的二分图。

预处理出所有的联通块,每个联通块用\((x,y)\)表示,意味着左边有\(x\)个,右边有\(y\)个。

于是就有了下面这个状压DP:\(f_{S,i}\)表示\(S\)集中的联通块都被使用了,其中完成了的联通块的\(x\)之和为\(i\)的最小边数。

等等,这个状态会不会存不下?

实际上,对于相同的\((x,y)\),我们只关心数量,所以可以进一步压缩。然后状态的数量就变得少了很多。

最后的答案记得要减去原来就有的边数。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 33
inline void update(int &x,int y){x>y?x=y:0;}
int n;
char can[N][N];
bool vis[N][2];
int cntl,cntr,have;
void find(int x,bool k){
vis[x][k]=1;
if (k==0){
cntl++;
for (int i=1;i<=n;++i)
if (can[x][i]=='1' && !vis[i][1])
find(i,1);
}
else{
cntr++;
for (int i=1;i<=n;++i)
if (can[i][x]=='1' && !vis[i][0])
find(i,0);
}
}
int sc[N][N];
struct State{
int x,y;
int num;
} lis[N];
int m;
int pro[N];
int chose[N];
int f[200000][N];
void dfs(int k,int s,int x,int y){
if (k>m){
if (s==0)
f[0][0]=0;
for (int j=0;j<n;++j){
if (x==y)
update(f[s][x],f[s][j]+(x-j)*(x-j));
for (int i=1;i<=m;++i)
if (chose[i]<lis[i].num)
update(f[s+pro[i-1]][j],f[s][j]);
}
return;
}
for (int i=0;i<=lis[k].num;++i){
chose[k]=i;
dfs(k+1,s+i*pro[k-1],x+i*lis[k].x,y+i*lis[k].y);
}
}
int main(){
freopen("factory.in","r",stdin);
freopen("factory.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%s",can[i]+1);
for (int j=1;j<=n;++j)
if (can[i][j]=='1')
have++;
}
for (int i=1;i<=n;++i){
if (!vis[i][0]){
cntl=cntr=0;
find(i,0);
sc[cntl][cntr]++;
}
if (!vis[i][1]){
cntl=cntr=0;
find(i,1);
sc[cntl][cntr]++;
}
}
pro[0]=1;
for (int i=0;i<=n;++i)
for (int j=0;j<=n;++j)
if (sc[i][j]){
lis[++m]={i,j,sc[i][j]};
pro[m]=pro[m-1]*(sc[i][j]+1);
}
memset(f,127,sizeof f);
f[0][0]=0;
dfs(1,0,0,0);
printf("%d\n",f[pro[m]-1][n]-have);
return 0;
}

总结

居然还有如此鬼畜的DP……

[JZOJ6299] 2019.08.12【NOIP提高组A】工厂的更多相关文章

  1. 2018.12.08【NOIP提高组】模拟B组总结(未完成)

    2018.12.08[NOIP提高组]模拟B组总结 diyiti 保留道路 进化序列 B diyiti Description 给定n 根直的木棍,要从中选出6 根木棍,满足:能用这6 根木棍拼出一个 ...

  2. 2017.08.08【NOIP提高组】模拟赛B组

    Summary 今天的题目也不算很难,唯一一道没做出来的题目是以前做过的,太不应该了. Problem T1 油滴扩展 题目大意 给你一堆点,你准备要在这么多的点当中滴油.你可以自己安排顺序,每次滴油 ...

  3. 2018.12.30【NOIP提高组】模拟赛C组总结

    2018.12.30[NOIP提高组]模拟赛C组总结 今天成功回归开始做比赛 感觉十分良(zhōng)好(chà). 统计数字(count.pas/c/cpp) 字符串的展开(expand.pas/c ...

  4. NOIP提高组2004 合并果子题解

    NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...

  5. [NOIP提高组2018]货币系统

    [TOC] 题目名称:货币系统 来源:2018年NOIP提高组 链接 博客链接 CSDN 洛谷博客 洛谷题解 题目链接 LibreOJ(2951) 洛谷(P5020) 大视野在线评测(1425) 题目 ...

  6. NOIP提高组初赛难题总结

    NOIP提高组初赛难题总结 注:笔者开始写本文章时noip初赛新题型还未公布,故会含有一些比较老的内容,敬请谅解. 约定: 若无特殊说明,本文中未知数均为整数 [表达式] 表示:在表达式成立时它的值为 ...

  7. 津津的储蓄计划 NOIp提高组2004

    这个题目当年困扰了我许久,现在来反思一下 本文为博客园ShyButHandsome的原创作品,转载请注明出处 右边有目录,方便快速浏览 题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津\ ...

  8. 计蒜客 NOIP 提高组模拟竞赛第一试 补记

    计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...

  9. 1043 方格取数 2000 noip 提高组

    1043 方格取数  2000 noip 提高组 题目描述 Description 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样 ...

随机推荐

  1. mysql-python不支持python3

    使用Mysqlclient pip3 install Mysqlclient

  2. pytest-mark跳过

    import pytestimport sysenvironment='android' @pytest.mark.skipif(environment=="android",re ...

  3. C语言之内存分配函数

    #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { /********* ...

  4. 微信小程序のwxs

    WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构. wxs可以说就是为了满足能在页面中使用js存在的,在wxml页面中,只能在插值{{ }}中写简单的j ...

  5. 2018-2-13-win10-uwp-如何拖动一个TextBlock的文字到另一个TextBlock-

    title author date CreateTime categories win10 uwp 如何拖动一个TextBlock的文字到另一个TextBlock lindexi 2018-2-13 ...

  6. Oracle之视图联合查询加排序问题

    在公司修改bug,有这样的需求:需要从两张视图中查出相同字段的数据,按照导师姓名先排序,再按照学号排序 union联合两张表,SELECT * from((SELECT DS_ID,PYLX_ID,Y ...

  7. 利用left join 筛选B表中不包含A表记录

    select A.key from A LEFT JOIN B ON A.KEY=B.KEY WHERE B.FIELD IS NULL;

  8. mysql 8+ 忘记root密码 解决方案

    在安装完数据库后,由于自己不小心直接关闭了安装窗口,或者长时间没有使用root用户登录系统,导致忘记了root密码,这时就需要重置MySQL的root密码.当然,最简单方式自然是删除数据库的data目 ...

  9. UDP部分

    IP地址:互联网协议地址,计算机的通行证.计算机在网络中的唯一身份标识.桥接:Ubuntu虚拟机 直接连到局域网NAT:网络地址转换点分十进制:192.168.14.115IP地址通常为4个字节,简称 ...

  10. Java——方法的重写(覆盖)

    2.2方法的重写(覆盖)(override,orverwrite) 2.2.1 什么时候方法要进行重写? 如果父类中的方法已经无法满足当前子类的业务需求,需要将父类中的方法进行重新写一遍.就是要改变父 ...