1. 程式人生 > >第十屆藍橋杯C語言校選難題

第十屆藍橋杯C語言校選難題

題目:填入0~9的數字。

要求:連續的兩個數字不能相鄰(左右、上下、對角都算相鄰)一共有多少種可能的填數方案?

                                                            

請填寫表示方案數目的整數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。

程式碼構成如下

 

頭部:
#include <stdio.h>

#define ROW 3   // 行數

#define COL 4   // 列數

int sum = 0;    // 可以成立的排列組合方案個數
 

迴圈遍歷陣列,當前位置的數字是否和其他存放位置的一樣。
// 填入的數字是否存在相同數字

int isT(int arr[][COL], int row, int col)

{

    // 迴圈所有陣列位置

    for (int i = 0; i < ROW; i++)

    {

    for (int j = 0; j < COL; j++)

    {

            // 判斷是否是自身位置, 因為自身位置一定等於自身

        if (row == i && col == j)

        continue;

            // 判斷數字是否相同 相同則返回真

        if (arr[i][j] == arr[row][col])

        return true;

    }

    }

    // 都不相同返回假

    return false;

}


判斷該數字的相鄰位置是否有連續數字,且當前數字是否重複出現。
// 填入的數字是否成立

int isReal(int arr[][COL], int row, int col)

{

    //迴圈相鄰的位置

    for (int i = row - 1; i <= row + 1; i++)

    {

    for (int j = col - 1; j <= col + 1; j++) 

    {

            //過濾九宮格超出陣列範圍的部分

        if (j >= 0 && j<COL && i >= 0 && i<ROW) 

        {

                //判斷是否相鄰  且 是否含有重複數字

        if (   arr[i][j] == arr[row][col] + 1 

                    || arr[i][j] == arr[row][col] - 1 

                    || isT(arr,row,col) ) 

        {

            return 0;

        }

        }

    }

    }

    return 1;

}
 

遞迴函式

數字填充遞迴路徑 , 相當於將二維陣列看成一位陣列,從最後一位開始變更數字,暴力破解的方式填充數字

                                                            


//遞迴的函式,用於暴力找出所有情況

void def(int arr[][COL], int row, int col, int num) //num為存放了多少個數字 相當於樹的深度

{

    num++;  //當前數字個數

    if (row > 2 || row<0 || col>3 || col < 0)//防止超出陣列範圍

    {

    return;

    }

    for (int i = 0; i < 10; i++)

    {

        arr[row][col] = i;

        // print(arr); //想看每一步的遞迴過程,請解開此註釋

        if (isReal(arr, row, col) && arr[row][col + 1] != -3)  //此處-3作為不可存放

        def(arr, row, col + 1, num);  //往右遞迴

        if (isReal(arr, row, col) && arr[row + 1][0] != -3) 

        def(arr, row + 1, 0, num);  //往下遞迴

        if (num == 10 && isReal(arr, row, col)) //已經存放10個數字,同時達到題目要求條件

        {

            // print(arr); //想看每一步成功填入的過程,請解開此註釋

            sum++;

        }

    }

    arr[row][col] = -2; //待填入的方格用-2表示

}
 

主函式
void main()

{

    // 賦值為-3 代表著是方塊不可寫入數字

    int arr[ROW][COL] = { 0 }; 

    for (int i = 0; i < 3; i++) // -2為待填入放個陣列

    for (int j = 0; j < 4; j++)

        arr[i][j] = -2;

    arr[0][0] = -3;  //-3禁止填入的位置,相當於牆

    arr[ROW - 1][COL - 1] = -3;

    def(arr, 0, 1, 0);

    printf("排列方式為%d種 \n", sum);

}
 

用來測試結果是否為真的程式碼

void print(int arr[][COL])

{

    for (int i = 0; i < ROW; i++)

    {

        for (int j = 0; j < COL; j++)

        {

            printf("%2d  ", arr[i][j]);

        }

        printf("\n");

    }

    printf("\n");

 

}