标签:
噗。。。这几道题题很简单。。实现起来也挺简单的。。但是。。。
虽然最终的solution很简单。。但是如何想出这个solution和如何实现这个问题(实现中的细节)也是要考虑的。。。。
恩。。在这里说一说拿到一道题的分析历程吧顺带总结一下(?)。。
-------------------------------------------------------
POJ 2337 Catenyms 欧拉回路
Description:给你n个单词,让每个单词的最后一个字母恰好等于下一个单词的第一个字母。构造这样一个串,使每个单词恰好被用到一次。取字典序最小的。
例如,把 aloha arachnid dog gopher rat tiger 串成 aloha.arachnid.dog.gopher.rat.tiger。 若所个的单词不能构成这样一个串,那么输出“***”。
我们拿到题第一步应该怎么分析?
最朴素的办法。。搜啊。。但是显然这题应该不是考你玩意儿。。
额。。。 我们先来想一想题目要你干的事情的本质是什么。。首先对于一个串。。它的有用的部分只有开头结尾两个字母。。于是我们可以看看样例。。
样例输出的答案其实无非就是a --> a -- > d --> g-->r --> t..
然后。。恩。。看着这个东西。。。。是不是很想建个图?? 恩我们发现每个单词就构造了一条边
这样就相当于用欧拉回路就可以解决了。。。。
然后无解的情况。。我们首先判定当前图是不是一个欧拉图【此题半欧拉图也是有解的】。。
- 1.是否是连通图【解决方法:遍历节点检查,并查集检查祖先是否唯一】
- 2.无向图:所有节点的度为偶数,或者有且只有两个度为奇数的节点。
有向图:起始点s的入度=出度-1,结束点t的出度=入度-1 或两个点的入度=出度
然后我们考虑细节。。字典序的话。。如果是欧拉图就从字典序最小的那个点开始。。半欧拉图不管。。注意此题是有向图
判定联通我们可以在输入的时候用并查集搞一搞。。或者dfs一下
所以我们也许可以得到一个模型。。就是
一个状态——>另一个状态,能否从其中一个状态开始可以完美的把每个状态访问正好一次
这种题的解决方案:哈密顿图可以。。欧拉图。。如果整个图可以是个回路的话那就用半欧拉图解决:即从出度比入度大一的点开始遍历。。
-----------------
POJ 2513 Colored Sticks 也是欧拉路。这道题的分析方法和上面一样。。
其实主要的考点有三个。。并查集。。哈希。。欧拉图的判定。。对只是判定。。
然后哈希这道题map会超时。。所以网上主流的办法就是trie然后把string映射成int。。
------------------------------------------------------
这道题。。。。poj个磨人的小妖精。上回我调了一下午 + 一晚上。。最后发现只是个memset的问题【法式微笑
关于memset的注意问题我在隔壁的错误集合里面有更详细解释。。。。
然后这题就是个括号配对。
这道题应该先怎么分析。。
我们先从题目描述入手:
定义合法的括号序列如下:
1 空序列是一个合法的序列
2 如果S是合法的序列,则(S)和[S]也是合法的序列
3 如果A和B是合法的序列,则AB也是合法的序列
然后我们就可以。。从题目下手。。轻。松。推出方程式。。。。【玛德为什么我第一遍写的时候就不会呢QAQAQ】
我们想要让S合法,我们按照题目描述一条一条来分析:
第一条。说明输入会有空串,所以我们需要输出回车。。
第二条告诉我们什么。当区间[i,j], i与j配对时,此时让S合法只需要考虑[i+1, j-1]的区间。。也就是说此时区间[i, j]需要添加的括号数就等于[i+1, j-1]。。。
然后我们考虑不配对的时候我们怎么让括号合法。。也就是第三条要告诉我们的。
这样的话就说明他们一定需要和ij之间的某两个括号配对。。同时这两个括号相邻。。。
我们可以。。。枚举这个两个区间从哪里断开。。也就是从哪个括号的后面分开。。。。最后需要添加的括号数就相当于两个区间之和。。然后我们需要让这个值尽量小。。
所以到这里转换方程就差不多出来了。
我们用f[i][j]表示区间[i, j]所需要添加的括号数量..可以得出
f[i][j] = f[i + 1][j - 1] (str[i] 配对 str[j])
f[i][j] = min(min{ f[i][k] + f[k + 1][j] }, f[i][j])(i <= k <= j)【此处即便楼上配对也要执行。。万一解更优呢是吧2333】
然后我们考虑初始化。。
我们初始化的目的是要保证它的每一个状态依靠的那个状态可达(已经有了值)。。
恩。。所以我们可以发现整个f数组赋值的地方是呈一个三角形。。右上部分。。因为扩展的k有i和j的限制。。。。
所以实际上我们是z形去扩展的。。所以我们把那一条对角线初始化成1就行了。。因为当i == j的时候。。这个区间一共只有一个括号。。所以一定要加一个括号来和它配对。。
我们一个for把i == j的初始化成1.然后剩下的时inf就行了。。。
然后注意一点我就是这么被坑的。其实可以不看所以我就折叠了
如果你是在dp的过程中赋inf那么要把f数组初始化为0.
【或者如果你是全局变量的话就不用了,编译器会给你赋0】。
或者你加一个判断就是在ij配对的情况下:
if(i + 1 <= j - 1) f[i][j] = f[i + 1][j - 1];
else f[i][j] = 0;
如果不加这个判断的话。。比如我这种喜欢开头memset赋inf的人就会错。。
但是在循环中赋INF的人就不会有这个问题。。
因为编译器自动把别的赋成0了【微笑&&不屑】
因为你输出f数组就会发现它是会影响f数组的。。。。
从我们代码里也可以看出。。这里就不解释了。。因为。。
我心累。。。。
不过奇怪的是memset 127就没问题0x3f就WA了。。可能是编译器字节问题吧。。
然后我们考虑怎么输出。。。恩就是如何记录路径然后输出。。
因为第一种ij配对的情况很好打印。。因为ij已知,所以
1.直接输出左括号,print(中间的区间), 然后输出右括号。
我们考虑第二种情况。我们可以记录它的断点,然后
2.print左区间,print右区间这样不断递归下去。
边界就是i > j和
3.当我们遇到单个括号的时候肯定是把另一半儿就直接输出了对吧。。。就是i == j
于是我们用一个pos来存断点。。也就是那个k。。
然后我们把第一种情况ij配对pos[i][j] 直接赋-1。。这样我们遇到-1就干楼上的1 如果有值的话就执行2 剩下i == j执行3
哦。不放代码了。因为这道题搞得我特别郁闷。特。别。郁。闷。。。。特!!!别!!!!!郁!!!!闷!!!
对了事实证明在dp过程中赋值逼memset inf快。一个16ms。一个0ms【微笑】然后。。。。
比较让我不解的是为什么我用了register int 结果比int还要慢啊2333以后还是不搞这些奇怪的常数优化了23333
总之这件事情告诉我们:
从题目入手。。从题目给你的任何你觉得有用的东西入手。。。注意每一个细节。。比如discuss里面就有许多人被那个空串坑了。但实际上题目已经说了空串是一个合法序列
----------------------------------------------------------
POJ 1789 Truck History 最小生成树
Description:用一个7位的string代表一个编号,两个编号之间的distance代表这两个编号之间不同字母的个数。一个编号只能由另一个编号“衍生”出来,代价是这两个编号之间相应的distance,现在要找出一个“衍生”方案,使得总代价最小,也就是distance之和最小。
呐。。。拿到这道题。。。我们先想想问题怎么转化。。
我们会发现一个编号由另一个编号衍生出来的代价是dis。。我们换个说法。。。从一个状态达到另一个状态的代价是dis。。
那么。。现在是不是有股冲动想要连个边。。。
所以我们建个图吧!!!然后我们用string的编号当做点。string之间的distance当做权值。。
然后我们考虑如何完成题目所说的。。题目想要求的我们想一想还能用什么来表达有助于我们思考。。
恩。。题目实际上就相当于让我们在一个图上找到一个新图。。这个新图要包含所有的点。。然后边权总和最小。。
呐!这不就是最小生成树了么!
然后我们斟酌一下用prim还是kruscal。。
因为每一个串一定可以转化成另外一个串,所以这个图是个完全图。。也就是说是一个稠密图。。。。。呐。就决定是prim辣嘿嘿嘿【噗。。。虽然我喜欢kruscal QAQQAQ】
所以其实本题的重点就在于转化成最小生成树。。。
噗。。。我要是别人不说我也想不出来这是最小生成树QAQ我真是太菜了QAQ
总之。。这道题又告诉了我们什么。转化十分重要。。然后
要学会把题目中的话和问题转化成有助于你分析的语句。。剩下的就靠条件反射和智商了2333333
-------------------------------------------
POJ 1062 昂贵的婚礼 最短路
233333难得的中文题啊。
然后dijkstra容易写。。但是我喜欢spfaQAQ
Description: QAQ中文题了宝宝就不写题目简述了QAQ。。
主要是在于如何转化。。。
我们这么想。。
我们看题目的这句话:
一个物品加上金币可以交换另一个物品
也就是说你的金币和东西变成了另一个东西。。换句话来说。。从一个状态转换到了另一个状态。。
这图就很明确了嘛。。。
我们考虑如何构图。一般来说这个主人公没有金币。。要不断的换东西才能得到金币。。整个是一个回溯的过程。。
所以也就是说。。主人公现在已经有了一个物品。。他还需要花费x个金币才能转化到另一个物品。。
所以我们就可以够构图了。。
物品A ---> 物品B,权值为所需要的金币。。
建完图之后其实解决方案就很明朗了。。。
最后要求的是最少的金币花费。。我们可以用0这个点表示我们最开始的状态。。然后目标点就是酋长的那个点。。
由於边权不会出现负权。。所以。。最短路随便用啦。我喜欢spfa。。。
然后还有一个问题就是等级限制。。这里我不会啊。。看了看解题报告。。原来是我没理解清楚题意。。
题目指的等级较高的人是对主人公假设一个值。。比主人公高的叫等级较高。。
所以。。我们。。可以枚举一下主人公的等级在最短路的时候加个判断就好了。只能与大于这个等级的人或者差距不超过限制的人交易。。然后我们扫一遍标记一下vis数组相当于筛掉他们。。
-------------------------------------
POJ 1125 Stockbroker Grapevine 最短路 || 传递闭包
Description:啊。。实在懒得写了。。实在不想写题目简述了啦QAQAQ
我们首先第一反应A——>B连边权值为传递代价。。。。然后。。。。然后就floyd传递闭包就行了。。。
然后注意一点就是说时间是可以重叠的所以是对每个点到达所有点的时间取max。。然后在max种取一个最小值。。。。
或者还有一种奇葩的做法23333每个点spfa2333333
心累。。。本来在txt里写了好多最后辣鸡电脑死机了没保存。。。。。。。。。。。。。。。。。。。。。。。。
实在不想写了QAQAQ
阔怕阔怕尊阔怕
------------------------------------------------
小结:
欧拉图的判定:
- 1.是否是连通图【解决方法:遍历节点检查,并查集检查祖先是否唯一】
- 2.无向图:所有节点的度为偶数,或者有且只有两个度为奇数的节点。
有向图:起始点s的入度=出度-1,结束点t的出度=入度-1 或两个点的入度=出度
写题时候的注意:
- 从题目入手。。从题目给你的任何你觉得有用的东西入手。。。
- 要学会把题目中的话和问题转化成有助于你分析的语句。。剩下的就靠条件反射和智商了2333333
- dp遵循一个原则就是上一状态一定要保证它可达。。
- 初始化的时候一定要考虑周全。。
- 理解清楚题意十分重要。。
- 注意每一个细节。。
其他的更多的都在另一个帖子了吧。。。
End.
标签:
原文地址:http://www.cnblogs.com/shadyqwq-juruo/p/5754083.html