先考虑第一个问题,即求最小的巧克力块数

将这张网格图建图(仅对$c_{i,j}\ne -1$的位置建点),即求点数最少的连通块(的点数)使得存在$k$个不同的$c_{i,j}$

(以下$c$仅用一维数组表示,$c_{i}$即表示编号为$i$的点的原来的$c_{i,j}$)

令$f_{i,S}$表示包含$i$且集合$S$中的$c_{i}$都在连通块中出现(仅要求出现,不要求其余点不出现)的点数最少的连通块(的点数),显然只需要求出这个dp数组即可,下面考虑如何求:

初始令$f_{i,0}=f_{i,\{c_{i}\}}=1$且$f_{i,j}=\infty$(其中$j>0$),之后不断利用以下几个递推式进行转移——
$$
S'\ne \empty且S'\subset S,f_{i,S}=\min(f_{i,S},f_{i,S'}+f_{i,S\setminus S'}-1)\\(i,j)\in E,f_{i,S}=\min(f_{i,S},f_{j,S}+1)
$$
换言之,只需要不断将其以此法进行修改直至无法修改即得到了正确的$f_{i,j}$,此做法正确性显然

虽然整体没转移有后效性,但第一个转移在$S$这一维上一定是从$S_{sub}$转移到$S$(其中$S_{sub}\subset S$),换言之若从小到大枚举$S$那么就可以从小到大枚举$S$,并求出对应的$f_{i,S}$(最终的值),那么一定是从前面转移

再用枚举子集的技巧优化,可以做到总计$o(n3^{C})$的复杂度(其中$C=\max c_{i}$)

更进一步的,第3个转移是一个最短路的形式(直接从dijkstra的角度来说,即对于最小的$f_{i,S}$具有后效性),当求完后再求一次类似最短路的过程即可

这里转移的复杂度是$o(n\log n\ 2^{C})$,在$C$较小时可以通过

(上面所述的也就是所谓的“斯坦纳树”,反正就是一个此类状压dp的计算方式)

当$C$较大时,上面的做法显然不行,但如果将这些$c_{i}$随机映射到$[1,k]$上(即令$C=k$),得到的解显然也是合法的(但并不一定最小)

考虑点数最小的答案是其中的某$k$个,那么只需要这$k$个中任意两个不映射到同一个位置上即可,这样的概率即为$\frac{k!}{k^{k}}$,若取$k=5$大约为0.0384

以此法做大约200次,求最小值即可得到一个较为准确的答案

另外还有需要最小化中位数,可以二分中位数$mid$,并将所有数分为0和1(小于等于$mid$或大于$mid$),在上面的状态基础上再定义一个$g_{i,S}$表示在$f_{i,S}$最小的基础上最少的1的个数即可

总复杂度为$o(TC\log A(n\log n\ 2^{k}+n3^{k}))$(其中$C=200$即操作次数,$A=\max a_{i,j}$),略卡常数

(另外测评时注意跳过样例,否则会Judgment Failed)

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 250
4 #define oo 0x3f3f3f3f
5 #define pii pair<int,int>
6 #define mp make_pair
7 #define fi first
8 #define se second
9 struct Edge{
10 int nex,to;
11 }edge[N<<2];
12 priority_queue<pair<pii,int> >q;
13 int V,E,t,n,m,k,id[N][N],c[N][N],val[N],vis[N],head[N],a[N];
14 pii ans,b[N],f[N][32];
15 pii add(pii x,pii y){
16 return mp(x.fi+y.fi,x.se+y.se);
17 }
18 pii neg(pii x){
19 return mp(-x.fi,-x.se);
20 }
21 void add(int x,int y){
22 edge[E].nex=head[x];
23 edge[E].to=y;
24 head[x]=E++;
25 }
26 void dijkstra(int S){
27 memset(vis,0,sizeof(vis));
28 for(int i=1;i<=V;i++)q.push(mp(neg(f[i][S]),i));
29 while (!q.empty()){
30 int k=q.top().second;
31 q.pop();
32 if (vis[k])continue;
33 vis[k]=1;
34 for(int i=head[k];i!=-1;i=edge[i].nex)
35 if (f[edge[i].to][S]>add(f[k][S],b[edge[i].to])){
36 f[edge[i].to][S]=add(f[k][S],b[edge[i].to]);
37 q.push(mp(neg(f[edge[i].to][S]),edge[i].to));
38 }
39 }
40 }
41 pii calc(int mid){
42 for(int i=1;i<=V;i++)
43 if (val[i]<=mid)b[i]=mp(1,0);
44 else b[i]=mp(1,1);
45 for(int i=1;i<=V;i++){
46 for(int j=1;j<(1<<k);j++)f[i][j]=mp(oo,0);
47 f[i][0]=f[i][(1<<a[i])]=b[i];
48 }
49 for(int i=1;i<(1<<k);i++){
50 for(int j=1;j<=V;j++)
51 for(int s=(i&(i-1));s;s=(i&(s-1)))f[j][i]=min(f[j][i],add(add(f[j][s],f[j][i^s]),neg(b[j])));
52 dijkstra(i);
53 }
54 pii ans=mp(oo,0);
55 for(int i=1;i<=V;i++)ans=min(ans,f[i][(1<<k)-1]);
56 return ans;
57 }
58 pii calc(){
59 int l=0,r=1e6,ans=calc(0).fi;
60 while (l<r){
61 int mid=(l+r>>1);
62 if (calc(mid).se<=ans/2)r=mid;
63 else l=mid+1;
64 }
65 return mp(ans,l);
66 }
67 int main(){
68 srand(time(0));
69 scanf("%d",&t);
70 while (t--){
71 scanf("%d%d%d",&n,&m,&k);
72 for(int i=1;i<=n;i++)
73 for(int j=1;j<=m;j++)scanf("%d",&c[i][j]);
74 V=E=0;
75 memset(head,-1,sizeof(head));
76 memset(id,0,sizeof(id));
77 for(int i=1;i<=n;i++)
78 for(int j=1;j<=m;j++){
79 if (c[i][j]>0){
80 id[i][j]=++V;
81 scanf("%d",&val[V]);
82 if ((i>1)&&(id[i-1][j])){
83 add(id[i-1][j],id[i][j]);
84 add(id[i][j],id[i-1][j]);
85 }
86 if ((j>1)&&(id[i][j-1])){
87 add(id[i][j-1],id[i][j]);
88 add(id[i][j],id[i][j-1]);
89 }
90 }
91 else scanf("%*d");
92 }
93 ans=mp(oo,0);
94 for(int times=0;times<200;times++){
95 memset(vis,-1,sizeof(vis));
96 for(int i=1;i<=n;i++)
97 for(int j=1;j<=m;j++)
98 if (c[i][j]>0){
99 if (vis[c[i][j]]<0)vis[c[i][j]]=rand()%k;
100 a[id[i][j]]=vis[c[i][j]];
101 }
102 ans=min(ans,calc());
103 }
104 if (ans.fi==oo)printf("-1 -1\n");
105 else printf("%d %d\n",ans.fi,ans.se);
106 }
107 }

[loj2977]巧克力的更多相关文章

  1. loj2977 巧克力 (斯坦纳树+随机化)

    考虑颜色比较少的时候,第一问可以直接斯坦纳树 第二问考虑二分,每次把每格的权值给成1000+[a[i]>m],就是在个数最少的基础上尽量选小于等于m的 然而颜色太多不能直接做,但可以把每种颜色映 ...

  2. 【THUSC2017】【LOJ2977】巧克力 斯坦纳树

    题目大意 有一个网格(或者你可以认为这是一个图),每个点都有颜色 \(c_i\) 和点权 \(a_i\). 求最小的连通块,满足这个连通块内点的颜色数量 \(\geq k\).在满足点数最少的前提下, ...

  3. Bzoj2850 巧克力王国

    Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 505  Solved: 204 Description 巧克力王国里的巧克力都是由牛奶和可可做成的.但 ...

  4. C Golden gun的巧克力

    Time Limit:1000MS  Memory Limit:65535K 题型: 编程题   语言: 无限制 描述 众所周知,13级有尊大神Golden gun,人称根叔,简称金枪!众立志进校队的 ...

  5. 分巧克力【来源:CSDN线上编程挑战赛】——递归,费波那奇数列,迭代

    /*====================================================================== 儿童节快到了,班长想要给班上的每个同学给一个巧克力, ...

  6. Luogu P2183 巧克力

    题目描述 佳佳邀请了M个同学到家里玩.为了招待客人,她需要将巧克力分给她的好朋友们.她有N(1<=N<=5000)块巧克力,但是大小各不一样,第i块巧克力大小为为1*Xi(1<=i& ...

  7. BZOJ2820 - 巧克力王国

    原题链接 Description 给出个二维平面上的点,第个点为,权值为.接下来次询问,给出,求所有满足的点的权值和. Solution 对于这个点建一棵k-d树,子树维护一个子树和. 如果子树所代表 ...

  8. [FWT] UOJ #310. 【UNR #2】黎明前的巧克力

    [uoj#310][UNR #2]黎明前的巧克力 FWT - GXZlegend - 博客园 f[i][xor],考虑优化暴力,暴力就是FWT xor一个多项式 整体处理 (以下FWT代表第一步) F ...

  9. 巧克力分配问题——C语言

    某品牌巧克力使用500克原料可制作55小块巧克力,请编程实现:输入原料重量(以千克为单位),计算出制作巧克力的块数(四舍五入).然后对这些巧克力进行分包,小盒放11块,大盒放24块,问各分装多少大盒多 ...

随机推荐

  1. 日常学习用到的Git指令

    Git 常用Git指令 (本地) git init - 将文件夹初始化为Git仓库 git add - 将工作区的指定文件放入暂存区 git status - 查看工作区和暂存区的状态 git com ...

  2. linux 安装libreOffice

    linux 安装libreOffice 第一种方式:通过yum install libreoffice* 安装,但在使用docx文档转化为pdf的过程中,发现有些表格样式出现变形,因此采用如下方式安装 ...

  3. 初步认识HCIA,什么是计算机网络,拓扑,网络的发展,交换机,路由器,IP,光纤,带宽,广播,ARP......

    HCIA ---- 华为认证初级网络工程师 云技术 --- 云存储 云计算 计算机技术 : ​ --- 抽象语言 -- 电线号的转换 抽象语言 -- 编码 ---- 应用层 编码 --- 二进制 -- ...

  4. SpringBoot入门01-环境部署

    随笔目录: 环境准备 创建过程 编码试行 环境准备 如果编辑器是还没有配置过相关环境的,在用SpringBoot开发项目的时候,需要先环境,spring boot官网建议的开发工具是: STS或Ide ...

  5. struts2漏洞复现分析合集

    struts2漏洞复现合集 环境准备 tomcat安装 漏洞代码取自vulhub,使用idea进行远程调试 struts2远程调试 catalina.bat jpda start 开启debug模式, ...

  6. Poetry(2)Poetry的基本使用方式

    Poetry的基本使用 准备工作 如果你是在一个已有的项目里使用Poetry,你只需要执行 poetry init 命令来创建一个 pyproject.toml 文件: poetry init 可看到 ...

  7. 在Vue&Element前端项目中,对于字典列表的显示处理

    在很多项目开发中,我们为了使用方便,一般都会封装一些自定义组件来简化界面的显示处理,例如参照字典的下拉列表显示,是我们项目中经常用到的功能之一,本篇随笔介绍在Vue&Element前端项目中如 ...

  8. UE4蓝图AI角色制作(六)之行为树

    13.行为树原理 AI最重要的环节就是行为树.我们将解释什么是行为树.为何它如此重要,以及构建行为树需要哪些元素. 借助行为树,我们可以轻松控制并显示AI的决策制定过程.行为树是一种将AI在场景中的决 ...

  9. Unity——EasyTouch摇杆插件使用

    EasyTouch摇杆插件使用 Demo展示 双指缩放在电脑端无法掩饰,竖屏将就看看吧: 插件名叫EasyTouch,有需要给我留言,不想开仓库传了: 创建摇杆点这里: 初始化 On_Joystick ...

  10. Python小工具:据说这是搜索文件最快的工具!没有之一!一起感受下......

    电脑自带的搜索文件功能相信大家都体验过,那是真的慢,等它找到文件,我都打完一把游戏了! 那必须不能忍,于是我自己做了一个文件搜索工具,犄角旮旯的文件都能一秒钟搜索出来的那种! 保证能把你们男(女)朋友 ...