結果

問題 No.663 セルオートマトンの逆操作
ユーザー snow4726snow4726
提出日時 2018-03-16 21:20:36
言語 C
(gcc 12.3.0)
結果
TLE  
実行時間 -
コード長 6,096 bytes
コンパイル時間 291 ms
コンパイル使用メモリ 30,336 KB
実行使用メモリ 8,736 KB
最終ジャッジ日時 2024-06-01 09:34:21
合計ジャッジ時間 7,165 ms
ジャッジサーバーID
(参考情報)
judge2 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
6,912 KB
testcase_01 AC 2 ms
5,248 KB
testcase_02 AC 1 ms
5,376 KB
testcase_03 AC 1 ms
5,376 KB
testcase_04 AC 1 ms
5,376 KB
testcase_05 AC 1 ms
5,376 KB
testcase_06 AC 1 ms
5,376 KB
testcase_07 AC 1 ms
6,940 KB
testcase_08 AC 1 ms
5,376 KB
testcase_09 AC 1 ms
5,376 KB
testcase_10 AC 1 ms
5,376 KB
testcase_11 AC 1 ms
5,376 KB
testcase_12 AC 1 ms
5,376 KB
testcase_13 AC 1 ms
5,376 KB
testcase_14 AC 1 ms
5,376 KB
testcase_15 AC 1 ms
5,376 KB
testcase_16 AC 1 ms
5,376 KB
testcase_17 AC 1 ms
5,376 KB
testcase_18 AC 1 ms
5,376 KB
testcase_19 AC 1 ms
5,376 KB
testcase_20 AC 1 ms
5,376 KB
testcase_21 TLE -
testcase_22 TLE -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

/**********************************************************
一次元セルオートマトンルール110を1段目に適用した結果である2段目が
与えられるのであり得る1段目の種類数を出力するプログラム
入力:列数N、2段目のi列目の数値0か1
出力:2段目を生成できる1段目の種類数を10^9+7で割った余り
**********************************************************/
#include<stdio.h>
#include<stdlib.h>

/* グローバル変数 */
int* first; /* 1段目の数列*/
int* second;    /* 2段目の数列 */
int n;  /* 列数N */

long long int saiki(int);  /* 1段目の数列の種類数を求める再帰関数 */
int ismatch(int, int, int, int, int, int, int);
/* 一次元セルオートマトンルールの上段の値の列毎の比較と一次元セルオートマトンの上段の値を仮定して決める関数 */

int main(){

    int i;  /* カウンタ */
    long long int count;  /* 1段目の数列の種類数 */

    scanf("%d",&n); /* 列数Nの入力 */

    first = (int*)calloc(n,sizeof(int));    /* 1段目の数列の領域確保 */
    second = (int*)calloc(n,sizeof(int));   /* 2段目の数列の領域確保 */

    for(i=0; i<n; i++){
        scanf("%d",second+i);   /* 2段目のi列目の数値の入力 */
    }

    count = saiki(0);    /* 再帰関数によって1段目の数列の種類数を求める */

    printf("%lld\n",count%1000000007);  /* 出力 */

    return 0;

}

/**********************************************************
1段目の数列の種類数を求める再帰関数
引数:現在の列
返戻値:1段目の数列の種類数
**********************************************************/
long long int saiki(int stage){

    long long int count = 0;  /* 1段目の数列の種類数 */
    int num1,num2,num3;   /* 一次元セルオートマトンの上段の3つを指定する数列の列数番号 */

    if( stage < n ){    /* 現在の列がn列目以下の時 */
        if( stage == 0 ){
            num1 = n - 1;   /* 1列目は一次元セルオートマトンの上段の左の列数はn列目 */
        }else{
            num1 = stage - 1;   /* 1列目以外は現在の列-1が一次元セルオートマトンの上段の左の列数 */
        }

        if( stage == n - 1 ){
            num3 = 0;   /* n列目は一次元セルオートマトンの上段の右の列数は1列目 */
        }else{
            num3 = stage + 1;   /* n列目以外は現在の列+1が一次元セルオートマトンの上段の右の列数 */
        }

        num2 = stage;   /* 一次元セルオートマトンの上段の真ん中の値の列数は現在の列 */
    }

    if( stage == n ){   /* 現在の列がn+1列目の時はその数列は1段目の数列と見なされる */
        count++;    /* 1段目の数列の種類数をカウント*/
    }else{  /* 探索中 */
        if( second[stage] == 0 ){   /* 2段目の現在の列の数値が0の場合 */
            if( ismatch(stage,num1,num2,num3,0,0,0) == 1 ) count += saiki(stage+1); /* 一次元セルオートマトンの上段が0,0,0の場合の比較、再帰 */
            if( ismatch(stage,num1,num2,num3,1,0,0) == 1 ) count += saiki(stage+1); /* 一次元セルオートマトンの上段が1,0,0の場合の比較、再帰 */
            if( ismatch(stage,num1,num2,num3,1,1,1) == 1 ) count += saiki(stage+1); /* 一次元セルオートマトンの上段が1,1,1の場合の比較、再帰 */
        }else{  /* 2段目の現在の列の数値が1の場合 */
            if( ismatch(stage,num1,num2,num3,0,0,1) == 1 ) count += saiki(stage+1); /* 一次元セルオートマトンの上段が0,0,1の場合の比較、再帰 */
            if( ismatch(stage,num1,num2,num3,0,1,0) == 1 ) count += saiki(stage+1); /* 一次元セルオートマトンの上段が0,1,0の場合の比較、再帰 */
            if( ismatch(stage,num1,num2,num3,0,1,1) == 1 ) count += saiki(stage+1); /* 一次元セルオートマトンの上段が0,1,1の場合の比較、再帰 */
            if( ismatch(stage,num1,num2,num3,1,0,1) == 1 ) count += saiki(stage+1); /* 一次元セルオートマトンの上段が1,0,1の場合の比較、再帰 */
            if( ismatch(stage,num1,num2,num3,1,1,0) == 1 ) count += saiki(stage+1); /* 一次元セルオートマトンの上段が1,1,0の場合の比較、再帰 */
        }
    }

    return count;
}

/************************************************************************
一次元セルオートマトンルールの上段の値の列毎の比較と
一次元セルオートマトンの上段の値を仮定して決める関数
引数:現在の列数、一つ前の列、現在の列、一つ後の列、一次元セルオートマトンの値3つ
返戻値:一次元セルオートマトンの上段の値の列毎の比較を行い全て等しいか否か
************************************************************************/
int ismatch(int stage, int num1, int num2, int num3, int i1, int i2, int i3){

    int flag = 0;   /* 一次元セルオートマトンの上段の値の列毎の比較に使うフラグ */

    if( stage >= n - 2 ){   /* 2段目の現在の列がn-1かn列目の時 */
        /* 一次元セルオートマトンの上段の値の列毎の比較 */
        if( first[num1] == i1 && first[num2] == i2 && first[num3] == i3 ) flag = 1;
    }else if( stage != 0 ){ /* 2段目の現在の列が1列目以外の時 */
        /* 一次元セルオートマトンの上段の値の列毎の比較 */
        if( first[num1] == i1 && first[num2] == i2 ){
            flag = 1;
            first[num3] = i3;   /* 次の列の一次元セルオートマトンの上段の値を仮定する */
        }
    }else{  /* 2段目の現在の列が1列目の時 */
        /* 一次元セルオートマトンの上段の値3つ全てを仮定する */
        first[num1] = i1;
        first[num2] = i2;
        first[num3] = i3;
        flag = 1;   /* 1列目の時は無条件で判定OKとする */
    }

    return flag;

}
0