uva1204 有趣的游戏

一些男生女生(一共至少2人)坐成一圈做游戏。游戏做n轮,每轮从任意一个人那里开始,顺时针逆时针数若干个人(不超过100个),把他们的性别分别记下来,于是每一轮游戏都得到一个B\G序列(B for boy G for girl)。给出n轮游戏的B\G序列,求可能的最少参与游戏人数。
例如,两轮的结果分别是BGGGBBBGG、BBGGG,那么最少可能有6个人:GGGBBB。
n<=16

方便起见,称一轮游戏的结果为一个串。如果某个串是另一个串的子串,那么这个串是没用的,预处理时丢弃掉。然后这个问题就好像是把这若干个串首尾相“粘”,拼成一个尽可能短的圈。


首尾相"粘"

关于这种构思的正确性,我们假定得到了最优解的环形序列,然后随意指定某个位置为起始位置0,编号顺时针逐位增加。那么每个串都是这个最优解的一部分,或者若干圈再加上一部分。接着按照起始编号从小到大给所有的串排序,由于预处理去掉了所有被包含的子串,所以不存在两个串起始编号相同的情况。规定每个串贡献的部分是它的起始位置到下一个串的起始位置之前,那么各个串的贡献无交集并且和为最优解。故而所有可能的最优解都可以用上图的形式表示,只需枚举所有这些可能的情况然后挑出其中绿色部分的和最大的一个,则灰色部分最小。

只有一个串的情况

另外需要注意只有一个串的情况,这时候相当于它自己的尾巴和自己的头重合了,一个串可以和自身完全重合,但绿色的部分应是除了这种情况以外的最大重叠部分。

程序实现上,先随意指定某个串作为起点,记为串0。
定义dp[s][i][t]为:当串的集合为s,正\反向串i作为终点时,圈中重叠部分和的最大值(t=0\1,正\反向)。注意s一定包含串0,并且串i和串0的重叠部分也要算在dp内(首尾相接)。决策是倒数第二个位置是s中的哪个串。

于是有转移方程:
dp[s][i][t] = max{dp[s-i][x][t']+rep[x,t'][i,t]-rep[x,t'][0,0]+rep[i,t][0,0]}
其中rep是两个各自有特定方向的串最大重叠部分,另外我们规定串0总是正向的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 8,734评论 0 2
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 6,154评论 0 2
  • 加入好报写作群后,我才知道简书。 前几篇日记都是在道云笔记上写好,再复制过来的。 现在回想起来感觉自己好傻,居然不...
    容码一生阅读 2,790评论 2 0
  • 夏日昏昏不愿醒, 夜深凄凄难入梦. 早时少年心天下, 今朝人老情故人. 漂流多载更漂流, 孤零深处最孤零. 人生何...
    _贾立松_阅读 819评论 4 0
  • 1.被安利了吃鸡这个游戏后,就像是中毒一样,和几个鸡友一起每天下午都要去跳伞送快递,简直不能自拔…… 2.我们群里...
    黑色大乌鸡阅读 1,800评论 0 0