浏览 2195 次
锁定老帖子 主题:谷哥的KOF连招问题
精华帖 (0) :: 良好帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-10-09
最后修改:2010-10-09
玩过KOF(拳皇)的人都知道,玩的时候会连招是比较强的。题目的大概意思是:每招用一个大写字母表示,如ABC...Z,现给定n个连招公式:S→T,其中S长度为m,T的长度为1。在前m招的时候可以随便连,但m+1招后就必须遵循连招公式。现在要写一个算法,计算最长连招的长度;如果可以无限连招,则返回def。1≤n,m≤100 给了一个例子:n=4,m=3,连招公式为:ABC→C,ABC→D,CCA→A,BCC→A。连招公式的意思是:A、B、C可以连出C,也可连出D,C、C、A可以连出A,B、C、A、可以连出B。这时候可以得到最长连招公式:ABC→C→A→A,即最长连招公式长度为6。 放十一长假闲着无聊,想了想具体解法;长假结束后抽出时间把算法完整写出来了。 首先是将问题转变成图论问题,需要将n中的每一个连招转化成图的邻接矩阵表示 ABC→C,ABC→D,CCA→A,BCC→A 转化成图的邻接矩阵为 0,0,0,1 0,0,0,0 0,0,0,0 0,0,1,0 (第一行0,0,0,1表示招式ABC-C后可以接BCC-A,第二行0,0,0,0表示ABC-D不能接任何连招,依次类推) 那么,首先判断是否def,即查找图中是否存在环,应用环中有反向边的定理(参照算法导论第22章:图的基本算法) 其查找def的关键代码如下 private boolean isDef() { initGraph(); for (int i = 0; i < hits.length; i++) { if (color[i].equals(Colors.WHITE)) { dfs(i); } } return isDef; } private void dfs(int index) { color[index] = Colors.GRAY; List<Integer> adj = getNextHits(index); for (int i = 0; i < adj.size(); i++) { if (color[adj.get(i)].equals(Colors.WHITE)) { dfs(adj.get(i)); } if (color[adj.get(i)].equals(Colors.GRAY)) { isDef = true; } } color[index] = Colors.BLACK; } 如果是非def的 那么求最长连招,需要找到矩阵中的全0行,进行逆向BFS,并同时维护一个最长连招数组。 其关键代码如下 int[] maxHits = new int[hits.length]; for (int i = 0; i < list.size(); i++) { Queue<Integer> queue = new Queue<Integer>(); queue.add(list.get(i)); maxHits[list.get(i)] = 1; while (!queue.isEmpty()) { int index = queue.front(); queue.delete(); List<Integer> adj = getPrevious_Hits(index); for (int j = 0; j < adj.size(); j++) { if (maxHits[adj.get(j)] < maxHits[index] + 1) { maxHits[adj.get(j)] = maxHits[index] + 1; queue.add(adj.get(j)); } } } } int max = 0; for (int i = 0; i < maxHits.length; i++) { if (maxHits[i] > max) { max = maxHits[i]; } } 具体可执行代码见附件。 PS1: 测试较少,希望童鞋们能提供更多的测试用例 PS2:getPrevious Hits这个方法,由于河蟹的佳爱不允许出现s-H-i-t这种不河蟹的单词,只能拆分为getPrevious_Hits,佳爱的河蟹词过滤该加油了 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |