2016编程之美初赛体验

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天的时间复习。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

Content is available under CC BY-SA 3.0 unless otherwise noted.