C语言程序设计基础|数独

题目一:数独验证

题目描述:

数独是一种填数游戏,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。

每个数独有唯一解。下图是一个数独填数后的解(黑色数字是已知数字,绿色数字是填数数字)。

输入填数后的9×9盘面,写函数判断其是否是解,返回1或0。

输入要求:

测试次数

每组测试数据是1个9*9的数字阵(元素值:1~9)

输出要求:

每组测试数据,如果满足数独要求,输出YES,否则输出NO

#include<iostream>
#include<cmath>
#include<iomanip>
#include<algorithm>
#include<cstring>
using namespace std;

int row(int arr[][10])
{
    int count[10], totalsub;//用count记录每个数字出现的次数,如果符合条件每个数字只出现一次
    for (int i = 1; i <= 9; i++)
    {
        memset(count, 0, 10 * sizeof(int));
        for (int j = 1; j <= 9; j++)
        {
            count[arr[i][j]]++;
        }
        totalsub = 1;
        for (int k = 1; k <= 9; k++)
        {
            totalsub *= count[k];//累乘只能等于1
        }
        if (totalsub != 1)
        {
            return 0;
        }
    }
    return 1;
}

int col(int arr[][10])//与行同理
{
    int count[10], totalsub;
    for (int i = 1; i <= 9; i++)
    {
        memset(count, 0, sizeof(int) * 10);
        for (int j = 1; j <= 9; j++)
        {
            count[arr[j][i]]++;
        }
        totalsub = 1;
        for (int k = 1; k <= 9; k++)
        {
            totalsub *= count[k];
        }
        if (totalsub != 1)
        {
            return 0;
        }
    }
    return 1;
}
int section(int arr[][10])
{
    int count[10], totalsub;
    for (int i = 1; i <= 9; i++)//一共有9个区域,必须全部符合
    {
        int relrow, relcol;
        relrow = ((i - 1) / 3) * 3 + 1;//找出9个区域对应的行列
        relcol = ((i - 1) % 3) * 3 + 1;
        memset(count, 0, sizeof(int) * 10);
        for (int j = relrow; j < relrow + 3; j++)//判断原理同上
        {
            for (int k = relcol; k < relcol + 3; k++)
            {
                count[arr[j][k]]++;
            }
        }
        totalsub = 1;
        for (int k = 1; k <= 9; k++)
        {
            totalsub *= count[k];
        }
        if (totalsub != 1)
        {
            return 0;
        }
    }
    return 1;
}

int main() {
    int t;
    cin >> t;
    while (t--)
    {
        int arr[10][10];
        for (int i = 1; i <= 9; i++)
        {
            for (int j = 1; j <= 9; j++)
            {
                cin >> arr[i][j];
            }
        }
        if (row(arr) && col(arr) && section(arr))//分为行列区域三个模块进行判断
        {
            cout << "YES" << endl;
        }
        else
        {
            cout << "NO" << endl;
        }
    }
    return 0;
}

问题二:数组求解

题目描述:

数独是一种填数游戏,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。

每个数独有唯一解。下图是一个数独填数后的解(黑色数字是已知数字,绿色数字是填数数字)。

在上题数独验证的代码上,增加函数,根据输入的9*9盘面已知数字,求解数独,并输出解。

输入要求:

输入1个9*9的数字阵,数字范围0-9,0表示该位置无数字,需填数。

输出要求:

输出数独解(9*9的矩阵值)

#include<iostream>
#include<cmath>
#include<iomanip>
#include<algorithm>
#include<cstring>
using namespace std;

int flag;
int simplerepeat(int arr[][10], int x, int y, int site)
{
    for (int i = 1; i <= 9; i++)//每一列不重复
    {
        if (arr[x][i] == site)//如果重复就返回0到上一级
        {
            return 0;
        }
    }
    for (int j = 1; j <= 9; j++)//每一行不重复
    {
        if (arr[j][y] == site)//如果重复就返回0到上一级
        {
            return 0;
        }
    };
    return 1;
}

int sectionrepeat(int arr[][10], int x, int y, int site)
{
    int partx, party;
    partx = ((x - 1) / 3) * 3 + 1;
    party = ((y - 1) / 3) * 3 + 1;
    for (int i = partx; i < partx + 3; i++)//每个区域里也不重复,如果重复就返回上一级
    {
        for (int j = party; j < party + 3; j++)
        {
            if (arr[i][j] == site)
            {
                return 0;
            }
        }
    }
    return 1;
}

void DFS(int arr[][10], int x, int y)
{
    if (y > 9)//如果列数大于9就换行
    {
        x++;
        y = 1;
    }
    if (x > 9)//如果行数大于9就输出最终解
    {
        for (int i = 1; i <= 9; i++)
        {
            for (int j = 1; j <= 9; j++)
            {
                cout << arr[i][j];
                if (j != 9)
                {
                    cout << " ";
                }
                else
                {
                    cout << endl;
                }
            }
        }
        return;
    }
    if (arr[x][y] == 0)
    {
        for (int i = 1; i <= 9; i++)
        {
            if (simplerepeat(arr, x, y, i) && sectionrepeat(arr, x, y, i))
            {
                arr[x][y] = i;//符合条件就赋值
                DFS(arr, x, y + 1);//然后遍历下一个位置
            }
        }
        arr[x][y] = 0;//遍历完返回上一级
    }
    else//有数就直接下一个位置
    {
        DFS(arr, x, y + 1);
    }
}

int main()
{
    int arr[10][10];
    for (int i = 1; i <= 9; i++)//输入需要求解的数独
    {
        for (int j = 1; j <= 9; j++)
        {
            cin >> arr[i][j];
        }
    }
    DFS(arr, 1, 1);
    return 0;
}
  • 8
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,这里提供一个简单的 C 语言代码示例,可以生成和解决数独。代码中使用了回溯算法求解数独,实现方法与前面提供的代码示例类似。 ```c #include <stdio.h> #include <stdlib.h> #include <time.h> // 定义数独的大小 #define N 9 // 定义数独 int sudoku[N][N] = { {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0} }; // 判断某个数是否可以填入某个位置 int can_place(int row, int col, int num) { // 判断当前行是否有相同数字 for (int i = 0; i < N; i++) { if (sudoku[row][i] == num) { return 0; } } // 判断当前列是否有相同数字 for (int i = 0; i < N; i++) { if (sudoku[i][col] == num) { return 0; } } // 判断当前子矩阵是否有相同数字 int sub_row = (row / 3) * 3; // 子矩阵的起始行号 int sub_col = (col / 3) * 3; // 子矩阵的起始列号 for (int i = sub_row; i < sub_row + 3; i++) { for (int j = sub_col; j < sub_col + 3; j++) { if (sudoku[i][j] == num) { return 0; } } } return 1; } // 随机填入数字 int fill_random(int row, int col) { if (row >= N) { return 1; } int arr[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; for (int i = 0; i < 9; i++) { int j = rand() % 9; int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } for (int i = 0; i < N; i++) { int num = arr[i]; if (can_place(row, col, num)) { sudoku[row][col] = num; if (col < N - 1) { if (fill_random(row, col + 1)) { return 1; } } else { if (fill_random(row + 1, 0)) { return 1; } } sudoku[row][col] = 0; } } return 0; } // 求解数独 int solve_sudoku(int row, int col) { // 如果当前行和列都大于等于 N,说明已经解出数独 if (row >= N && col >= N) { return 1; } // 如果当前列大于等于 N,换行 if (col >= N) { row++; col = 0; } // 如果当前位置已经填有数字,跳过 if (sudoku[row][col] != 0) { return solve_sudoku(row, col + 1); } // 尝试填入数字 for (int i = 1; i <= N; i++) { if (can_place(row, col, i)) { sudoku[row][col] = i; // 递归求解下一个位置 if (solve_sudoku(row, col + 1)) { return 1; } // 如果无解,回溯 sudoku[row][col] = 0; } } // 如果所有数字都不能填入当前位置,无解 return 0; } // 输出数独 void print_sudoku() { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf("%d ", sudoku[i][j]); } printf("\n"); } } int main() { // 随机生成数独 srand((unsigned int) time(NULL)); fill_random(0, 0); // 输出数独 printf("随机生成的数独为:\n"); print_sudoku(); // 求解数独 if (solve_sudoku(0, 0)) { // 输出结果 printf("数独的解为:\n"); print_sudoku(); } else { // 无解 printf("无解!\n"); } return 0; } ``` 这个代码可以随机生成数独,并使用回溯算法求解数独。生成数独的方法与前面提供的代码示例类似,不同的是它是随机填入数字,而不是从输入中读取数字。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

再给艾克三年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值