TOC
关于题目
BOP 的难度和 Code Hunt 根本不是一个难法。相比之下,Pex4Fun 和 Code Hunt 区更多地是以考验洞察力为主。
今天参加的 BOP2016 PRELIM A 共有两个 Sector 。很不幸的是,我最终只能成功提交一道题(00.04)。另有两道题则一直被 path bound exceeded 的错误困扰。
另请参阅:BOP2016 PRELIM A Leaderboard
00.01
输入为 `float[] a` ,输出为 `int[]`,包含了 a 中对应元素在整个 a 中的排名(从 0 开始),需要考虑并列排名的情况,有些类似于 Excel 的 `RANK` 函数。
思路:生成一个 [0, x.Length) 区间的整数序列 `ind`,然后使用 `Array.Sort(a, ind)` 进行排序。再开辟一个数组 `rank`,则此时 `ind[i]` 就意味着顺序排名第 `i` 的元素在排序前的原数组 `a` 中的位置。
本题较为麻烦的地方在于,如何处理并列排名的情况。我使用了双层循环。
以下是核心代码的残骸
// (r1,c1) and (r2,c2) are pairs of x-y coordinates
public static int[] Puzzle(double[] a)
{
var ind = Enumerable.Range(0, a.Length).ToArray();
Array.Sort(a, ind);
var rk = new int[a.Length];
var cur = 0;
for (int i = 0; i < a.Length; i++)
{
int j;
for (j = i + 1; j < a.Length && a[j] == a[i]; j++)
{ }
for (int k = i; k < j; k++)
{
rk[ind[k]] = cur;
}
cur += j - i;
i = j - 1;
}
return rk;
}
结果:path bound exceeded
后来使用 `Array.IndexOf` 代替内层第一个循环,问题依旧。
00.02
说实话,这道题,我并没有看出来什么规律。IQ捉急。
后来群里有人说,这是几何平均数。
好吧。
| a | Result |
|---|---|
| {1, 1, 1, 1, 1} | 1 |
| {1, 1, 1, 1} | 1 |
| {1, 1, 1} | 1 |
| {1, 1} | 1 |
| {1, 2} | 1 |
| {1} | 1 |
| {2, 1, 1, 1} | 1 |
| {2, 1} | 1 |
| {2, 2, 1} | 1 |
| {3, 1} | 1 |
| {5, 5, 1, 1, 1} | 1 |
| {2} | 2 |
| {3, 4, 5, 6} | 4 |
| {4} | 4 |
| {10, 5} | 7 |
| {10, 6} | 7 |
| {13, 4} | 7 |
| {4, 14, 7} | 7 |
| {5, 10} | 7 |
| {8, 7} | 7 |
00.03
这道题的输入比较复杂。此处列出其函数头
// (r1,c1) and (r2,c2) are pairs of x-y coordinates public static string Puzzle(int r1, int c1, int r2, int c2, string[] strs);
其中,`strs`指定了一个地图。地图中的 . 表示通路, # 表示障碍。需要求出从坐标 (r1, c1) 到达 (r2, c2) 的最短路径长度。如果没有可行通路,则返回 `”No path found!”`。
以下给出三个测试用例
CASE 1 (0,0) (2,6) 12 ".#....." ".#.#.#." "...#.#." CASE 2 (0,0) (0,2) 6 ".#." ".#." "..." CASE 3 ? <-- 因为 path bound exceeded 而无法显示参考结果 (0,0) (5,8) "........." "####.####" "...#.#..." ".#...#.#." ".#...#.#." ".#...#.#."
思路:当然是使用 BFS 啦~ 用队列解决一切问题。为了能把每一步的行、列和路程保存下来,最好做一个类或者结构体。
结果:path bound exceeded
由于代码过于惨不忍睹,此处就不贴上来了。
只知道最后为了试着解决这个问题,我甚至将 BFS 换成了 DFS + 距离启发 (<– 不知道是不是在瞎胡搞)。最后,比赛结束了……
00.04
输入一个 `int n`,按顺序输出所有可能的、包含 `n` 个左括号的、左右括号匹配的字符串列表。
思路:使用一棵树来表示每个字符的选择。由于每个字符只能选择`'(‘`、`’)’`之一,因此,最后会得到一棵二叉树。只要使用 DFS + 剪枝就可以了。分支截至字符串中的左括号数量等于 `n`,剪掉所有右括号数量大于左括号的节点。
代码如下
private class Node
{
public bool LP;
public Node Parent;
public int LPCount;
public int OpenLPs;
public int State = 0;
public Node L()
{
return new Node(true, LPCount + 1, OpenLPs + 1, this);
}
public Node R()
{
if (OpenLPs == 0) return null;
return new Node(false, LPCount, OpenLPs - 1, this);
}
public override string ToString()
{
var n = this;
var st = new Stack<char>();
while (n != null)
{
st.Push(n.LP ? '(' : ')');
n = n.Parent;
}
return string.Join(null, st);
}
public Node(bool lp, int lpCount, int openLPs, Node parent)
{
LP = lp;
Parent = parent;
LPCount = lpCount;
OpenLPs = openLPs;
}
}
public static string[] Puzzle(int n)
{
// the strings contain only parentheses
if (n <= 0) return new[] { "" };
if (n == 1) return new[] { "()" };
var list = new List<string>();
var root = new Node(true, 1, 1, null);
var st = new Stack<Node>();
st.Push(root);
// States
// 0 Nothing
// 1 L visited
// 2 R visited
while (st.Count > 0)
{
var nd = st.Peek();
if (nd.LPCount == n && nd.OpenLPs == 0)
{
list.Add(nd.ToString());
st.Pop();
continue;
}
switch (nd.State)
{
case 0:
nd.State = 1;
if (nd.LPCount < n)
{
var l = nd.L();
if (l != null) st.Push(l);
}
break;
case 1:
nd.State = 2;
var r = nd.R();
if (r != null) st.Push(r);
break;
case 2:
st.Pop();
break;
}
}
return list.ToArray();
}
结果:系统评级为1(It worked!),7分。这也是本场唯一拿到分的题目。
01.xx
很不幸,我没能活着从 TAIHU 出来。不知道 POYANG 如何(会不会像 PEX4FUN 的 Sector 03 一样)。
Epilogue
今年,大赛分为编程赛与创意赛,编程赛分初赛,复赛和决赛三部分。初赛和复赛在网络比赛平台上举行。今年初赛的网络平台为 Code Hunt平台。比赛时间为4月23日至4月24日,每天进行一场,时间为14:00-16:00。每场晋级1500人,共决出3000人晋级复赛。 [1]
按照今天 Code Hunt 的排名情况,似乎只要做出一道题,就能晋级了。不知道。总之,革命尚未成功,同志仍需努力。
今年的项目只有codehunt,各位oi/acm选手准备好被都是bug的平台玩奶子吧 [2]
我还是继续去 Coursera 上刷网课吧。在此之前……
我的工程优化好像还有4天的时间复习。
我的随机过程好像还有14天的时间复习。

