zoukankan      html  css  js  c++  java
  • [国家集训队2011]happiness(吴确)…

    题目:
    高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。


    分析:
    首先不用想,这肯定是个最小割……不妨将其解题过程记录下来,以作为一个典型的最小割模型题。

    “最小割”求的是一个“最小”的值,而本题需要最大化喜悦值之和,所以很显然,在最小割中被割掉的边应该意味着“放弃该喜悦值”。也就是说,最小割是放弃掉的所有喜悦值。

    首先,为了简单起见,我们不妨选取一对相邻点进行研究。不妨设是这样的:
    [国家集训队2011]happiness(吴确)解题报告

    其中S是源点,x,y是我们研究的两个点(也就是原问题中的两个学生),T是汇点。为了方便起见,没有画出边。

    文中可能会用到一些符号:w(a,b)表示边(a,b)的容量,x选文的喜悦值为W_x文,x,y都选文的额外喜悦值是W_同文,以此类推。

    最小割模型常用的一个手段是:每个点都需要在“在S集”和“在T集”两个事件中选一个。我们规定,“在S集”代表学文,“在T集”代表学理。

    那么总的快乐值是:W_x文 + W_x理 + W_y文 + W_y理 + W_同文 +W_同理,割值就是从其中扣掉的快乐值。

    下面考虑四种情况:
    ①x在S,y在S
    [国家集训队2011]happiness(吴确)解题报告
    红线代表割,左边是S集,右边是T集。
    割边容量之和:w(x,T) + w(y,T)
    “放弃的快乐值”之和:W_x理 + W_y理 + W_同理 (两个人同时学文)
    即:w(x,T) + w(y,T) = W_x理 + W_y理 + W_同理

    ②x在S,y在T
    [国家集训队2011]happiness(吴确)解题报告
    x学文,y学理。
    w(x,T) + w(S,y) + w(x,y) = W_x理 + W_y文 + W_同文 + W_同理

    类似可以推出后两种情况:
    x在T,y在S:w(S,x) + w(y,T) + w(y,x) = W_x文 + W_y理 + W_同文+ W_同理
    x在T,y在T:w(S,x) + w(S,y) = W_x文 + W_y文 + W_同文

    把四种情况写在一起:

    ①SS:w(x,T) + w(y,T)= W_x理 + W_y理 + W_同理

    ②ST:w(x,T)+ w(S,y) + w(x,y) = W_x理 + W_y文 + W_同文 + W_同理

    ③TS:w(S,x)+ w(y,T) + w(y,x) = W_x文 + W_y理 + W_同文 + W_同理

    ④TT:w(S,x)+ w(S,y) = W_x文 + W_y文 + W_同文

    然后,怎么设置这些边的容量呢?

    我们看①,左边有两项,右边有三项。
    秉承“对称”的思想,我们令:
    w(x,T) = W_x理 + 0.5W_同理,
    w(y,T) = W_y理+ 0.5W_同理。
    类似地,
    w(S,x) = W_x文 +0.5W_同文,
    w(S,y) = W_y文 +0.5W_同文。

    然后我们检查②和③。以②为例,将w(x,T)和w(S,y)代入并化简:

    w(x,y) = 0.5 ( W_同文 + W_同理 )

    看上去还不错!同样地由③得:

    w(y,x) = 0.5 ( W_同文 + W_同理 )

    把x,y扩展至整张棋盘:
    对于某个人(i,j),设它对应的顶点是x。
    连边(S,x),容量为:W_x理 + 0.5 ( x和所有邻居的W_同理之和) 
    连边(x,T),容量为:W_x文 + 0.5 ( x和所有邻居的W_同文之和 )
    对于某两个相邻的人x和y(y可能在x的上下左右),
    连边(x,y),容量为:0.5 ( W_同文 + W_同理 )

    用所有的快乐值之和(其实就是输入的那六个矩阵的所有元素之和)减去最小割(即最大流)的值即为答案。这里有一点细节:实数容量的网络流不好求,可以把所有边的容量*2,最后输出答案时/2即可。

    代码1:

    其实还有另外一种方法。

    回到①的那种情况。我们将整张棋盘黑白染色,那么x,y中有且仅有一个是黑的。
    不妨设x黑,那么令:
    w(x,T) = W_x理 + W_同理
    w(y,T) = W_y理

    类似地,y一定为白色,令:
    w(S,x) = W_x文
    w(S,y) = W_y文 + W_同文

    (把W_同文加在w(S,x)上其实也行,但这并不重要)

    将其代入②,③:
    w(x,y) = 0 
    w(y,x) = W_同文 + W_同理

    类似,对于一般的棋盘:
    某黑格x:
    w(x,T) = W_x理 + ( x和所有邻居的W_同理之和 )
    w(S,x) =W_x文

    某白格y:
    w(y,T) = W_y理
    w(S,y) = W_y文 + ( y和所有邻居的W_同文之和 )

    对于相邻的两人x,y,其中x黑y白:
    w(x,y) = 0
    w(y,x) = W_同文 + W_同理

    代码2:

    还有一个代码,是上面所说把W_同文也加到w(S,x)上的。
    代码3:

    测试结果是:2跑得最快,3和1差不多,都比较慢。这是因为,2对于每对邻居只建了一条边,而1,3都是建了两条。
  • 相关阅读:
    ARP:地址解析协议,RARP
    pip 安装psutil 报错 error: command 'gcc' failed with exit status 1
    linux shell 控制脚本
    linux shell 呈现数据
    linux shell 处理用户输入
    shell结构化命令
    centos7 安装配置 squid作为正向代理
    linux基本脚本
    linux文件权限
    模拟垃圾分布
  • 原文地址:https://www.cnblogs.com/wmdcstdio/p/7554264.html
Copyright © 2011-2022 走看看