寻找组织单向火车站交通算法的缺陷

时间:2017-11-11 11:15:29

标签: c algorithm stack

我编写了以下代码来解决this railway station traffic programming contest question。 (您可以阅读评论和建议的解决方案here)。但是,有一些例外情况,这些代码不会起作用。它们是什么?

#include <stdio.h>
#include <stdlib.h>
int main(){
    int n, i,j;
    int * array;
    scanf("%i",&n);
    array = malloc(sizeof(int) * n);
    for(i=0;i<n;++i) scanf("%i",&array[i]);
    for(i=0;i<n;++i){
        if(i+1 == array[i]) array[i] = -1;
        else{
            if(array[i] < i+1){
                for(j=0;j<i;++j){
                    if(array[i] == j+1){
                        if(array[j] == -1){
                            printf("No\n");
                            return 0;
                        }
                        else array[i] = array[j] = -1;
                    }
                }
            }
        }
    }
    for(i=0;i<n;++i) if(array[i] != -1) break;
    if(i == n) printf("Yes\n");
    else printf("No\n");
    return 0;
}

P.S。:我假设这个程序每次都有一个条目(而不是等待0来表示输入结束)。

此代码应执行的操作:

1)我假设你已经阅读what's in this link

2)将序列复制到数组后,我们必须验证该序列是否有效。

所以我们使用以下算法:

  1. 从第一个元素开始迭代序列。

  2. 如果element = element的索引+ 1(因为C列表是零索引的),则element = -1。

  3. 否则,当且仅当元素&lt; element的索引:我们查找前一个元素(当前元素== previous&#39; element index + 1)有效。如果找到此元素,则现在将当前元素和前一元素都更改为-1。如果之前的元素已经被更改过(也就是说,它已经是-1),那么这不是一个有效的序列。

  4. 如果在遍历列表之后仍然保留任何元素,则这不是有效序列。

  5. 示例:

      

    示例1

         

    数组:5 4 3 2 1

         

    5:5&gt; 0 + 1,跳过。 4:4> 1 + 1,跳过。 3:3 == 2 + 1.然后3 - > -1

         

    数组:5 4 -1 2 1

         

    2:2&lt; 3 + 1. 4的指数为1且1 + 1 = 2。

         

    数组:5 -1 -1 -1 1

         

    1:1&lt; 4 + 1.5具有0和0 + 1 = 1的索引。

         

    数组:-1 -1 -1 -1 -1

         

    因此该序列有效。

         

    示例2

         

    数组:5 4 1 2 3

         

    5:5&gt; 0 + 1,跳过。 4:4> 1 + 1,跳过。 1:1&lt; 1:1 2 + 1.5有一个索引   0。

         

    数组:-1 4 -1 2 3

         

    2:2&lt; 3 + 1. 4的指数为1.

         

    数组:-1 -1 -1 -1 3

         

    3:3&lt; 4 + 1. -1(在位置2)的指数为2. 2 + 1 = 3。   因此序列无效。

1 个答案:

答案 0 :(得分:1)

以下是输入的示例,其中您的代码将提供错误的输出:

5
3 4 2 5 1

您的说明用英语翻译了代码,但没有深入了解该算法解决问题的原因。所以,我只是寻求一个解决方案,其中使用额外的阵列来跟踪车站中的车厢,这些车厢必须像堆栈一样运作(先入后出):

#include <stdio.h>
#include <stdlib.h>
int main(){
    int n, i;
    int carriageAtA = 1;
    int * array;
    int * station;
    int stationSize = 0;
    // Read input
    scanf("%i",&n);
    array = malloc(sizeof(int) * n);
    station = malloc(sizeof(int) * n);
    for(i=0;i<n;++i) scanf("%i",&array[i]);
    // Iterate the desired carriages in sequence
    for(i=0;i<n;++i) {
        // While the last one in the station is not what we need:
        while ((!stationSize || station[stationSize-1] != array[i]) && carriageAtA <= n) {
            printf("Move %i from A to station\n", carriageAtA);
            // Last carriage in station B is not what we need, so pull one in from A:
            station[stationSize] = carriageAtA;
            stationSize++; // There is now one more carriage in the station
            carriageAtA++; // This is the next carriage at A
        }
        if (!stationSize || station[stationSize-1] != array[i]) {
            // Could not find desired carriage at A nor at station. Give up.
            printf("No\n");
            return 0;
        }
        // Drive last carriage at station to B:
        printf("Move %i from station to B\n", array[i]);
        stationSize--;
    }
    printf("Yes\n");
    return 0;
}

其他printf调用仅用于获取进程的视图。当你满意时删除它们。