zoukankan      html  css  js  c++  java
  • poj_2676

    大致题意:

    九宫格问题,也有人叫数独问题

    把一个9行9列的网格,再细分为9个3*3的子网格,要求每行、每列、每个子网格内都只能使用一次1~9中的一个数字,即每行、每列、每个子网格内都不允许出现相同的数字。

     

    0是待填位置,其他均为已填入的数字。

    要求填完九宫格并输出(如果有多种结果,则只需输出其中一种)

    如果给定的九宫格无法按要求填出来,则输出原来所输入的未填的九宫格

     

    解题思路:

    DFS试探,失败则回溯

     

    用三个数组进行标记每行、每列、每个子网格已用的数字,用于剪枝

    bool row[10][10];    //row[i][x]  标记在第i行中数字x是否出现了

    bool col[10][10];    //col[j][y]  标记在第j列中数字y是否出现了

    bool grid[10][10];   //grid[k][x] 标记在第k个3*3子格中数字z是否出现了

     

    row 和 col的标记比较好处理,关键是找出grid子网格的序号与 行i列j的关系

    即要知道第i行j列的数字是属于哪个子网格的

     

    首先我们假设子网格的序号如下编排:


    由于1<=i、j<=9,我们有: (其中“/”是C++中对整数的除法)


    a= i/3 , b= j/3 ,根据九宫格的 行列 与 子网格 的 关系,我们有:


     

    不难发现 3a+b=k

    即 3*(i/3)+j/3=k

    有了这个推导的关系式,问题的处理就变得非常简单了,直接DFS即可

    (以上是神牛的思路,只要是grid数组适用的太精辟了)

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    #pragma warning(disable : 4996)
    int n;
    int map[10][10];
    bool row[10][10];  //记录每行的数字是否可行
    bool col[10][10];  //记录没列的数字是否可行
    bool grid[10][10]; //记录每个九宫格的数字是否可行
    
    void CreateMap()
    {
    	char str[10] = {0};
    	for(int i = 0; i < 9; i++)
    	{
    		scanf("%s", str);
    		for(int j = 0; j < 9; j++)
    		{
    			map[i][j] = str[j] - '0';
    			if(map[i][j] != 0)
    			{
    				int num = map[i][j];
    				int k = 3 * (i / 3) + j / 3;  // 这个公式很关键。这是求每个点对应的九宫格
    				row[i][num] = true;
    				col[j][num] = true;
    				grid[k][num] = true;
    			}
    		}
    	}
    }
    
    bool dfs(int i,int j)
    {
    	bool flag = false;
    	if(i == 9) return true;
    	if(map[i][j] != 0)
    	{
    		if(j == 8)
    		{
    			flag = dfs(i + 1, 0);
    		}
    		else
    		{
    			flag = dfs(i, j + 1);
    		}
    		if(flag)   //在这回溯,但不改变map的值,只起到一个传递的作用
    			return true;
    		else
    			return false;
    	}
    	else
    	{
    		int k = 3 * (i / 3) + j / 3;
    		for(int x = 1; x <= 9; x++)
    		{
    			if(!row[i][x] && !col[j][x] && !grid[k][x])
    			{
    				map[i][j] = x;
    				row[i][x] = true;
    				col[j][x] = true;
    				grid[k][x] = true;
    				if(j == 8)
    				{
    					flag = dfs(i + 1, 0);
    				}
    				else
    				{
    					flag = dfs(i, j + 1);
    				}
    
    				if(!flag)    //这也是一个回溯
    				{
    					map[i][j] = 0;
    					row[i][x] = false;
    					col[j][x] = false;
    					grid[k][x] = false;
    				}
    				else
    				{
    					return true;
    				}
    			}//if
    		}//for
    	}
    	return false;
    }
    
    void output()
    {
    	for(int i = 0; i < 9; i++)
    	{
    		for(int j = 0; j < 9; j++)
    		{
    			printf("%d", map[i][j]);
    		}
    		printf("\n");
    	}
    }
    
    int main()
    {
    	freopen("in.txt","r",stdin);
    	scanf("%d", &n);
    	while(n--)
    	{
    		memset(row, false, sizeof(row));
    		memset(col, false, sizeof(col));
    		memset(grid, false, sizeof(grid));
    		CreateMap();
    		dfs(0, 0);
    		output();
    	}
    	return 0;
    }



  • 相关阅读:
    安装好php后找不到php.ini
    Nginx 和 PHP 的两种部署方式比较
    高性能Web服务之lnmp架构应用
    >/dev/null 2>&1的含义
    LC_ALL=C的含义
    深入理解PHP Opcode缓存原理
    iostat 监视I/O子系统
    sar 找出系统瓶颈的利器
    Linux常用命令汇总
    linux增加自定义path和manpath
  • 原文地址:https://www.cnblogs.com/lgh1992314/p/5835093.html
Copyright © 2011-2022 走看看