Chinaunix首页 | 论坛 | 博客
  • 博客访问: 832254
  • 博文数量: 330
  • 博客积分: 9641
  • 博客等级: 中将
  • 技术积分: 3181
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
文章分类

全部博文(330)

文章存档

2012年(17)

2011年(135)

2010年(85)

2009年(57)

2008年(36)

我的朋友

分类:

2011-05-10 23:16:58

     共4题,2011-05-08早上7点开始的,我10点钟起来时,在scoreboard上已经发现很多100分了。25points可以进入下一轮,我用来近10个小时才完成一题,由于第一题只有20分,所以我还要做一题。第二题做了,还调试了一遍都没对,就放弃去睡觉了。后来发现是我没有理解好opposed的属性(your whole element list will be cleared),所以没有正确完成题目,代码没有问题,但是理解错啦。
    我先说我做的两个题目。

    第一题:Bot Trust
两个99米的长廊每隔1m放置一个button,机器人O和B分别在两个长廊的第一个button处。机器人向前移动一格耗费一秒,向后移动一格也耗费一秒,按下button也要耗费一秒,停留在原地等待的时间也是以秒为单位的。两个机器人互不干扰,但是一个机器人O,必须等待另一个机器人B做完当前所有动作并按下按钮后才能按下按钮,而按按钮之前可以随意的移动和等待。现在要根据给定的输入顺序,求出两个机器人完成动作的时间总和。
例如给定序列:O 2, B 1, B 2, O 4

Time | Orange | Blue -----+------------------+----------------- 1 | Move to button 2 | Stay at button 1 2 | Push button 2 | Stay at button 1 3 | Move to button 3 | Push button 1 4 | Move to button 4 | Move to button 2 5 | Stay at button 4 | Push button 2 6 | Push button 4 | Stay at button 2
输入的文件第一行是需要处理的问题总数T,下面跟着的T行,每一行第一个数N表示后面跟着N个按照顺序需要按的按钮。
输出只要显示每行最小的耗费时间即可。
下面是我的程序,所有的异常都考虑到啦,像是一个程序员写的程序,不像算法比赛:
#include
#include
#include

#define LARGE_N 100

int find_next(char **cont, const int num, const int cur)
{
    int i;

    /* Only 'O' and 'B',find next different color robot */
    for (i = cur + 1i < num++i)
        if (cont[cur][0] != cont[i][0])
            return i;

    /* means all the remaining steps are the same robot */
    return 0;
}

void proc(char **cont, const int num, int *step, int *minute)
{
    /* at least need 2 item to calculate the time */
    if (*step >= num - 1)
        return;

    int cur = *step, next;
    int lastpos[2] = {*minute, 1};

    for (;;)
    {
        next = find_next(cont, num, cur);
        if (next == 0)
        {
            while (cur < num - 1)
            {
                *minute += abs(atoi(&cont[cur+1][1]) - atoi(&cont[cur][1])) + 1;
                ++cur;
            }
            break;
        }

        /* calculate */
        int cmptime[2] = {0, 0};
        while (cur < next - 1)
        {
            cmptime[0] += abs(atoi(&cont[cur+1][1]) - atoi(&cont[cur][1])) + 1;
            ++cur;
        }
        /* 比较下一个不同颜色移动的时间,和这一个颜色移动的时间。
         * 原因是下一个颜色可以在这一个颜色移动的同时移动 */
        /* next颜色robot可能向前或向后移动,所以加入abs() */
        int diff = abs(atoi(&cont[next][1]) - lastpos[1]) - (cmptime[0] + lastpos[0]);
        if (diff <= 0)
            cmptime[1] = 1;
        else
            cmptime[1] = diff + 1;

        /* 计算下一个不同颜色的robot的第一个格子耗费时间 */
        lastpos[0] = cmptime[1];
        /* 计算这个颜色的robot,作为下下个robot时的上一个格子的位置 */
        lastpos[1] = atoi(&cont[next-1][1]);
        cur = next;
        *minute += cmptime[0] + cmptime[1];
    }

    *step = cur;
    return;
}

void free_content(char **cont, int num)
{
    if (cont == NULL)
        return;
    while (num--)
        free(cont[num]);
    free(cont);
}

int main(int argc, char **argv)
{
    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        //printf("bad happen when opening file.\n");
        exit(1);
    }

    char *line = NULL;
    size_t len = 0;
    ssize_t read;
    read = getline(&line, &len, fp);
    //printf("len:%d, ret:%d(include '\\n'), val:%s", len, read, line);

    int total = atoi(line);
    if (total >= 1 && total <= 100)
        ;//printf("T: %d\n", total);
    else
    {
        //printf("T is not in range: %d\n", total);
        free(line);
        fclose(fp);
        exit(1);
    }

    char **content = NULL;
    content = (char **)malloc(LARGE_N * sizeof(char *));
    int i;
    for (i = 0i < LARGE_N++i)
        content[i] = (char *)malloc(sizeof("O 100"* sizeof(char));

    int j;
    for (j = 0j < total++j)
    {
        int num, retbits, totalbits = 0;
        getline(&line, &len, fp);
        sscanf(line, "%d %n", &num, &retbits);
        totalbits += retbits;
        //printf("num:%d, totalbits:%d\n", num, totalbits);

        for (i = 0i < num++i)
            memset(content[i], 0, sizeof("O 100"));

        for (i = 0i < num++i)
        {
            sscanf(line + totalbits, "%c %3[0-9] %n", &content[i][0], &content[i][1], &retbits);
            //printf("ret:%d, value:%s\n", retbits, content[i]);
            totalbits += retbits;
        }

        /* core idea,开始想做一个递归函数,所以加入step变量 */
        int minute = 0, step = 0;
        minute += atoi(&content[0][1]);
        proc(content, num, &step, &minute);

        printf("Case #%d: %d\n", j + 1, minute);
    }

    free_content(content, LARGE_N);
    free(line);
    fclose(fp);
    return 0;
}

    第二题:Magicka
有若干种基本元素,像是 {Q, W, E, R, A, S, D, F} 字母表中的其他字母表示合成元素。两个基本元素可以合成一个合成元素,比如QF合成T。我们用三个字母的组合QFT,来表示一个字符串中只要出现QF或者FQ就变成一个字母T,这叫combine。
另一种叫做opposed的方式。是当进行完combine之后,整个字符串中还存在两个字母的组合,比如VC,整个当前字符串就消失。比如VBFC 变成空。
输入文件第一行T表示下面有T行需要处理的字符串。每一行第一个数字C表示后面有几个3个字母组成的combine,第二个数字D表示后面有几个2个字母组成的opposed,第三个数字N表示后面要处理的字符串的长度。对长度为N的字符串先用combine规则,再用opposed规则就可以输出结果了。
输出的结果字符串要求是python里面的list的形式。
我很辛苦的写了一个程序,但是没有理解opposed里面整个list都消失了的含义,把问题给搞复杂了,遗憾。本来想python也许更简单,但是有第一题的读文件格式的架子,就用c了,后来发现python狂easy。
下面是官方Contest Analysis 里面对于这个问题的python伪代码:
# Let combo_list contain all the combinations as 3-letter strs.
# Let opposed_list contain all the opposed elements as 2-letter strs.
# Let invoke be a str containing the elements to invoke.
combos = dict()
opposed = dict()
for x in combo_list:
  combos[x[0] + x[1]] = x[2]
  combos[x[1] + x[0]] = x[2]
for x in opposed_list:
  opposed.add(x[0] + x[1])
  opposed.add(x[1] + x[0])
# Now combos contains a mapping from each pair to the thing it
# creates.  If one of the combinations was "ABC", then
# combos["AB"] = "C" and combos["BA"] = "C".
# opposed is filled in a similar way.

element_list = []
for element in invoke:
  # If element_list isn't empty, the last element might combine
  # with the element being invoked.
  if element_list:
    last_two = element_list[-1] + element
    if last_two in combos:
      element_list[-1] = combos[last_two]
    continue

  # Now we iterate through element_list to see if anything there
  # is opposed to the element being invoked.
  wipe_list = False
  for e in element_list:
    if (e + elementin opposed:
      wipe_list = True
  if wipe_list:
    element_list = []
    continue

  # There was no combination and no erasing: just append the
  # element to the list.
  element_list.append(element)

阅读(1076) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~

makao0072011-05-22 02:36:00

round1b 只做出了一题得20分。

makao0072011-05-21 11:45:24

早上的第一轮刚结束,只做了第一题的小数据集,得了7分,别提多郁闷了。

laoliulaoliu2011-05-19 15:02:26

makao007: 我也只做了两题,用Python实现,在理解题意上花了近一半的时间,也会出现会错题意导致不能accept。.....
最后回顾的时候发现其实思想很简单,被我们这些程序员搞复杂了。
是搞算法,不是搞工程。

makao0072011-05-16 22:40:59

我也只做了两题,用Python实现,在理解题意上花了近一半的时间,也会出现会错题意导致不能accept。