Copyright (C) IOI日本委員会 1996. All rights reserved.


問題5.

 系図を親子関係によって表したファイルが与えられている。英字1文字は一人の人 を表し、入力ファイルの1行には、親と子がこの順に書いてある。この系図上で、 最も長くつづいた系列をすべて求めたい。例えば、下記の入力ファイルに対しては、 図のような系図が対応し、このとき求める系列は、(例1)ではSDNFであり、(例2) ではTBCとHOFである。
 空欄を埋めて、プログラムを完成させよ。 [2点]

(例1)

入力ファイル   系図               出力結果
 SA      +---> A --> K     SD |        SDNF  AK S --|  DN |  NF      +---> D --> N --> F

(例2)

入力ファイル   系図               出力結果
 TB T --> B --> C     BC TBC  HO H --> O --> F HOF  OF      


QuickBASICプログラム(5)

DEFINT A-Z
DECLARE SUB search (s AS INTEGER, level AS INTEGER)
CONST false = 0, true = -1
DIM SHARED parentChild(ASC("A") TO ASC("Z"), ASC("A") TO ASC("Z")) AS INTEGER
DIM SHARED path AS STRING
DIM SHARED maxPath AS STRING
DIM SHARED maxLength AS INTEGER

    OPEN "input.txt" FOR INPUT AS 1
    FOR x = ASC("A") TO ASC("Z"): FOR y = ASC("A") TO ASC("Z")
        parentChild(x, y) = false 
    NEXT y: NEXT x
    WHILE NOT EOF(1)
        LINE INPUT #1, s$
        x = ASC(LEFT$(s$, 1)): y = ASC(RIGHT$(s$, 1))
        parentChild(x, y) = true
    WEND
    CLOSE 1

    maxLength = 0: path$ = "": maxPath$ = ""
    FOR x = ASC("A") TO ASC("Z"): FOR y = ASC("A") TO ASC("Z")
        IF parentChild(x, y) THEN path$ = CHR$(x): CALL search(y, 2)
    NEXT y: NEXT x

    WHILE LEN(maxPath$) > 0
        PRINT MID$(maxPath$, 1, maxLength)
        maxPath$ = MID$(maxPath$, maxLength+1)
    WEND
END

SUB search (c AS INTEGER, level AS INTEGER)
    path$ = path$ + CHR$(c)
    IF level > maxLength THEN
        maxLength = level: maxPath$ = path$
    ELSEIF level = maxLength THEN
        maxPath$ = maxPath$ + path$
    END IF
    FOR d = ASC("A") TO ASC("Z")
                                   ---------------------------
        IF parentChild(c, d) THEN |          (a)            |
                                   ---------------------------
    NEXT d
    -------------------------
   |        (b)            |
    -------------------------
END SUB


Cプログラム(5)

#include <stdio.h>
#include <string.h>

typedef enum { false, true } BOOLEAN;

BOOLEAN parent_child['Z'+1]['Z'+1];
char path[26], max_path[26];
int  max_length;

void search(char c, int level)
{
    char d;

    path[level]=c; path[level+1]='\0';
    if (level>max_length) {
        max_length=level; strcpy(max_path,path);
    }
    else if (level==max_length) strcat(max_path,path);
    for (d='A'; d<='Z'; d++) 
                                -----------------
        if (parent_child[c][d])|     (a)       |;
                                -----------------
    -------------------------
   |        (b)            |
    -------------------------
}

void main()
{
    char x,y,buf[10]; FILE *f;

    f=fopen("input.txt","r");
    for (x='A'; x<='Z'; x++) for (y='A'; y<='Z'; y++) 
        parent_child[x][y]=false;
    while (fgets(buf,10,f)!=NULL) {
        sscanf(buf,"%c%c", &x,&y); parent_child[x][y]=true;
    }
    fclose(f);

    max_length=0; path[0]='\0'; max_path[0]='\0';
    for (x='A'; x<='Z'; x++) for (y='A'; y<='Z'; y++)
        if (parent_child[x][y]) { path[0]=x; search(y,1); }

    while (strlen(max_path)>0) {
        strncpy(path,max_path,max_length+1); puts(path);
        strcpy(max_path,&max_path[max_length+1]);
    }
}


Pascalプログラム(5)

program problem5;
var parent_child:array['A'..'Z', 'A'..'Z'] of boolean;
    path,max_path:string; max_length:integer;

    procedure search(c:char; level:integer);
    var d:char;
    begin
        path:=path+c;
        if level>max_length then begin max_length:=level; max_path:=path end
        else if level=max_length then max_path:=max_path+path;
        for d:='A' to 'Z' do 
                                 -----------------
            if parent_child[c,d]|     (a)       |;
                                 -----------------
        -------------------------
       |        (b)            |
        -------------------------
    end; {search}

var x,y:char; f:text;

begin
    assign(f,'input.txt'); reset(f);
    for x:='A' to 'Z' do for y:='A' to 'Z' do parent_child[x,y]:=false;
    while not eof(f) do begin
        readln(f,x,y); parent_child[x,y]:=true
    end;
    close(f);

    max_length:=0; path:=''; max_path:='';
    for x:='A' to 'Z' do for y:='A' to 'Z' do
        if parent_child[x,y] then begin path:=x; search(y,2) end;

    while length(max_path)>0 do begin
        writeln(copy(max_path,1,max_length));
        delete(max_path,1,max_length)
    end
end.


JOI'96へ戻る

JOIホームページへ戻る