前阵子参加了Google的code jam,没有编程功底的人果然过不了第一关,不过事后重新做做还是挺有意思的,例如第一轮第三场的第二题,题目如下:

小明玩个游戏,一开始有N个火车车厢,每个车厢里都有字母,现在要组装火车,要求把所有车厢连在一起组成字符串,这个字符串要求相同的字母只能相邻,问现在有几种组装的方式。例如有三个车厢a,a,ab,组装的方式就有123,213两种。

题目讲完,现在来分析题目,先来考虑一个简单的情况,各个车厢的字母都是不一样的,相互独立,那么这时可拼装的方式一共有N!种,这也是题目最大的组装方式数。那么,我们需要把所有车厢的状态转化成上述独立状态,为了达到以上要求,需要首先处理每个车厢连续重复的字母,方便统计,然后处理所有单个字母,把所有相同的单个字母合并在一起,此时合并后的车厢内部可交换方案数目为字母数的阶乘,接着把单个字母和其他有相同结尾或开头的多个字母合并,合并后的车厢内部可交换方案数目为两个车厢可交换数的乘积,这样一来,原来单个字母的车厢要么已经合并,要么就跟其他所有车厢的字母都不一样,处理完单个字母,最后再把多个字母的车厢合并,合并后的车厢内部可交换数目为合并前两个车厢可交换数的乘积。上述处理结束后,假设还剩M个车厢,各个车厢的内部可交换数为A1,A2,...,Am,那么最后火车组装的方式一共有M!*A1*A2*...*Am,需要注意的是,处理车厢前需要检查各个车厢是否满足相同字母只能相邻的条件,然后处理车厢结束后,检查拼在一起的一种方案中组成的字符串是否满足相同字母只能相邻的条件。

解题思路就讲到这里,下面就直接上代码吧。

首先车厢的数据结构,包括车厢字符串,字符串里单个字母的数量,内部可交换的数目,以及一个表示车厢是否被合并过的,是否有效的布尔型。

struct train{bool isValid;int oneNum;unsigned long long exchange;string name;train():isValid(true),oneNum(0),exchange(1){};
};

然后就是合并单个字母函数

void mergeOneLetter(train* trainset,int len){for (int i=0; i<len; i++) {train& currentTrain=trainset[i];if (currentTrain.isValid&¤tTrain.name.length()==1) {//先把所有单个字符合并for (int j=i+1; j<len; j++) {train& otherTrain=trainset[j];if (otherTrain.isValid&&otherTrain.name.length()==1&&otherTrain.name[0]==currentTrain.name[0]) {currentTrain.oneNum++;currentTrain.exchange*=currentTrain.oneNum;otherTrain.isValid=false;}}//再合并多个字符的,确保单个字符要么不能连,要么已经合并不再是单个字符,方便下一步for (int j=0; j!=i&&j<len; j++) {train& otherTrain=trainset[j];if (otherTrain.isValid) {if (otherTrain.name[0]==currentTrain.name[0]) {otherTrain.isValid=false;stringstream mergeStream;mergeStream<<currentTrain.name<<otherTrain.name;currentTrain.name=mergeStream.str();currentTrain.exchange*=otherTrain.exchange;break;}if (otherTrain.name[otherTrain.name.length()-1]==currentTrain.name[0]) {otherTrain.isValid=false;stringstream mergeStream;mergeStream<<otherTrain.name<<currentTrain.name;currentTrain.name=mergeStream.str();currentTrain.exchange*=otherTrain.exchange;break;}}}}}
}

接着是合并其他车厢的函数

//合并所有火车
void mergeAllTrain(train* trainset,int len){for (int i=0; i<len; i++) {train& currentTrain=trainset[i];if (currentTrain.isValid) {currentTrain.isValid=false;char firstChar=currentTrain.name[0],lastChar=currentTrain.name[currentTrain.name.length()-1];int firstOccur=-1,lastOccur=-1;while ((firstOccur=findFirstLetter(trainset, len, lastChar))!=-1) {train& headTrain=trainset[firstOccur];headTrain.isValid=false;stringstream mergeStream;mergeStream<<currentTrain.name<<headTrain.name;currentTrain.name=mergeStream.str();currentTrain.exchange*=headTrain.exchange;lastChar=currentTrain.name[currentTrain.name.length()-1];}while ((lastOccur=findLastLetter(trainset, len, firstChar))!=-1) {train& tailTrain=trainset[lastOccur];tailTrain.isValid=false;stringstream mergeStream;mergeStream<<tailTrain.name<<currentTrain.name;currentTrain.name=mergeStream.str();currentTrain.exchange*=tailTrain.exchange;firstChar=currentTrain.name[0];}currentTrain.isValid=true;}}
}

附上判断一个车厢是否满足相同字母只能相邻的代码,判断整列火车方法也类似。

//判断一个train是否有效
bool judgeOneTrain(const train& theTrain){set<char> occurSet;string testString=theTrain.name;occurSet.insert(testString[0]);for (int i=1; i<testString.length(); i++) {char letter=testString[i];if(letter!=testString[i-1]){if (occurSet.find(letter)!=occurSet.end()) {return false;}else{occurSet.insert(letter);}}}return true;
}

最后,这道题我只过了小数据,因为要过大数据,涉及大数阶乘,要用数组辅助,我也不想做了。

codejam round1c第二题相关推荐

  1. /* * 编程第二题(20分): 一球从100米高度自由落下,每次落地后反跳回原高度的一半,再落下。求它在第十次落地时,共经过多少米?第十次反弹多高? */

    题目: /* * 编程第二题(20分): 一球从100米高度自由落下,每次落地后反跳回原高度的一半,再落下.求它在第十次落地时,共经过多少米?第十次反弹多高? */ 我是用java做的 public ...

  2. 2021年人工神经网络第三次作业-第二题:遗传算法与人工神经网络-参考答案

    简 介: 给出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程.所使用的遗传算法是最基本的遗传算法.利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化.对于不同的遗传 ...

  3. 2021年春季学期-信号与系统-第一次作业参考答案-第二题

      本文是: 2021年春季学期-信号与系统-第一次作业参考答案 的参考答案. ▌第二题: 写出下图所示的各波形的函数表达式: 第一小题: 求解: 这个函数可以使用分段函数来表示: 可以利用∣t∣\l ...

  4. 2020年人工神经网络第二次作业-参考答案第二题

    如下是 2020年人工神经网络第二次作业 中第二题的参考答案. ➤01 第二题参考答案 1.题目分析 (1) 训练样本 训练样本是低分辨率(5×5)字符,可以使用长度为25的向量表示,下面就是字母C, ...

  5. 第九届蓝桥杯java B组—第二题方格计数(详细介绍)

    文章目录 1.题目如下 2.解题思路 3.详细讲解 4.代码实例 5.答案 最近正在练习蓝桥杯的习题,做到第九届篮球杯的第二题(方格计数)的时候,发现没有思路,就上网上查了一些资料,感觉说的不够详细, ...

  6. 2014百度之星资格赛第二题

    Disk Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  7. 简单易懂的 pwnable.kr 第二题[collision]Writeupt

    简单易懂的 pwnable.kr 第二题[collision]Writeupt 题目地址:http://pwnable.kr/play.php 题目如下: 和第一题一样,题目给了我们一个ssh远程登录 ...

  8. 2012百度之星冬季赛第二场第二题 消去游戏I

    2012百度之星冬季赛第二场第二题 消去游戏I 题目: Alice和Bob又开始发明新游戏了,这回的名字叫消去游戏. 消去游戏的道具是一堆排成一行的积木,每个积木上面都有一个数字Ai.同时游戏也需要M ...

  9. CSDN挑战编程——《金色十月线上编程比赛第二题:解密》

    金色十月线上编程比赛第二题:解密 题目详情: 小强是一名学生, 同时他也是一个黑客. 考试结束后不久,他惊讶的发现自己的高等数学科目居然挂了,于是他果断入侵了学校教务部网站.在入侵的过程中,他发现了与 ...

最新文章

  1. 智能交通系统无人机派罚单,人脸成为下一个人牌号,人工智能下谁敢犯规
  2. 自动给文本框输入值_Dynamo for Revit自动生成门窗图例详图
  3. 获取当前div以外所有部分
  4. kettle mysql 参数_kettle参数、变量详细讲解
  5. isinstance_Java类class isInstance()方法及示例
  6. Linux学习-X Server 配置文件解析与设定
  7. Ajax Control Toolkit--Slider:有朝一日倒过来
  8. 对长度为200的有序表进行二分查找_程序员常用的查找算法(顺序、二分、插值、分块、斐波那契)...
  9. scrapy常用设置参考手册
  10. Atlassian JIRA 插件开发之一 环境搭建
  11. 航空概论(历年资料,引之百度文库,PS:未调格式,有点乱)
  12. ajax爬取微博,自动滚屏抓取新浪微博
  13. 镁光固态硬盘用什么软件测试寿命,最简单的方法:如何查看SSD可以使用多长时间?固态硬盘寿命测试方法[详细]...
  14. 利用OpenCV实现一个简单的实时人脸检测项目并显示FPS
  15. kubectl命令的使用、滚动更新以及回滚操作
  16. 集合的特性(成员操作符、for循环遍历)
  17. (1)ENVI-met项目介绍
  18. bilibili 哔哩哔哩 2018秋招试题
  19. 教你如何创建一个免费的网站
  20. spring 1.0-5.0版本注解发展史(一)

热门文章

  1. BDE与ADO的比较
  2. 一个30岁的人给你提个醒:不管收入多少,你一定要养成存钱习惯
  3. 给一些女生提供公司常用的英文女生名字。分别从A-Z
  4. 从零开始的Java笔记01
  5. Leetcode算法Java全解答--41. 缺失的第一个正数
  6. Unity 材质替换工具说明
  7. 经济高效 无盘组网设备选购方案(转)
  8. 户口迁入深圳的优劣势一览
  9. Spring AOP中定义切点的详细介绍
  10. java 神剑_java语音短信的实现