zoukankan      html  css  js  c++  java
  • [COGS 0407][NOIP 2009] 靶形数独

    407. [NOIP2009] 靶形数独

    ★★   输入文件:sudoku.in   输出文件:sudoku.out   简单对比
    时间限制:5 s   内存限制:128 MB

    【问题描述】 

    小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目。 
    靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的) 。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1到 9 的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。 (如图) 


    上图具体的分值分布是:最里面一格(黄色区域)为 10 分,黄色区域外面的一圈(红色区域)每个格子为 9 分,再外面一圈(蓝色区域)每个格子为 8分,蓝色区域外面一圈(棕色区域)每个格子为 7分,最外面一圈(白色区域)每个格子为 6 分,如上图所示。比赛的要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法) ,而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 2829。游戏规定,将以总分数的高低决出胜负。 


    由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的最高分数。

     【输入】 

    输入文件名为 sudoku.in。 
    一共 9 行。每行 9 个整数(每个数都在 0—9 的范围内) ,表示一个尚未填满的数独方格,未填的空格用“0”表示。每两个数字之间用一个空格隔开。 

    【输出】 

    输出文件 sudoku.out共 1行。 
    输出可以得到的靶形数独的最高分数。如果这个数独无解,则输出整数-1。 
     

    【输入输出样例 1】 

    sudoku.in

    7 0 0 9 0 0 0 0 1 
    1 0 0 0 0 5 9 0 0 
    0 0 0 2 0 0 0 8 0 
    0 0 5 0 2 0 0 0 3 
    0 0 0 0 0 0 6 4 8 
    4 1 3 0 0 0 0 0 0 
    0 0 7 0 0 2 0 9 0 
    2 0 1 0 6 0 8 0 4 
    0 8 0 5 0 4 0 1 2

    sudoku.out 

    2829 

    【输入输出样例 2】 

    sudoku.in

    0 0 0 7 0 2 4 5 3 
    9 0 0 0 0 8 0 0 0 
    7 4 0 0 0 5 0 1 0 
    1 9 5 0 8 0 0 0 0 
    0 7 0 0 0 0 0 2 5 
    0 3 0 5 7 9 1 0 8 
    0 0 0 6 0 1 0 0 0 
    0 6 0 9 0 0 0 0 1 
    0 0 0 0 0 0 0 0 6

    sudoku.out 

    2852 

    【数据范围】 

    40%的数据,数独中非 0数的个数不少于 30。 
    80%的数据,数独中非 0数的个数不少于 26。 
    100%的数据,数独中非 0 数的个数不少于 24。

     这题乍一看让人感觉一脸不可做的样子

    表示我的内心一脸懵逼甚至还想学 $DLX$

    结果实际上打了个最为暴力的暴搜就过了...

    大概搜索思路: 开三个数组保存九宫格/行/列中是否出现过某数, 然后开两个用来记录某下标的得分权值与所属九宫格编号.

    然后 $DFS$ 搜索枚举每个未知位置的可能值, 枚举时根据三个数组判一下是否在该行/列/九宫格内出现过. 发现可行解后更新答案.

    然后就AC了=_=...一脸懵逼.png

    参考代码

    GitHub

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream>
     5 #include <algorithm>
     6 typedef std::pair<int,int> Point;
     7 
     8 const int MAXN=20;
     9 
    10 const int score[MAXN][MAXN]={{0},
    11 {0,6,6,6,6, 6,6,6,6,6},
    12 {0,6,7,7,7, 7,7,7,7,6},
    13 {0,6,7,8,8, 8,8,8,7,6},
    14 {0,6,7,8,9, 9,9,8,7,6},
    15 {0,6,7,8,9,10,9,8,7,6},
    16 {0,6,7,8,9, 9,9,8,7,6},
    17 {0,6,7,8,8, 8,8,8,7,6},
    18 {0,6,7,7,7, 7,7,7,7,6},
    19 {0,6,6,6,6, 6,6,6,6,6}};
    20 const int block[MAXN][MAXN]={{0},
    21 {0,1,1,1,2,2,2,3,3,3},
    22 {0,1,1,1,2,2,2,3,3,3},
    23 {0,1,1,1,2,2,2,3,3,3},
    24 {0,4,4,4,5,5,5,6,6,6},
    25 {0,4,4,4,5,5,5,6,6,6},
    26 {0,4,4,4,5,5,5,6,6,6},
    27 {0,7,7,7,8,8,8,9,9,9},
    28 {0,7,7,7,8,8,8,9,9,9},
    29 {0,7,7,7,8,8,8,9,9,9}};
    30 
    31 int ans=-1;
    32 int known;
    33 int unknown;
    34 Point u[MAXN*MAXN];
    35 bool col[MAXN][MAXN];
    36 bool row[MAXN][MAXN];
    37 bool visited[MAXN][MAXN];
    38 
    39 void Initialize();
    40 void DFS(int,int);
    41 
    42 int main(){
    43     Initialize();
    44     DFS(unknown,known);
    45     printf("%d
    ",ans);
    46     return 0;
    47 }
    48 
    49 void DFS(int rest,int sum){
    50     if(rest==0){
    51         ans=std::max(ans,sum);
    52         return;
    53     }
    54     else{
    55         for(int i=1;i<=9;i++){
    56             if(!visited[block[u[rest].first][u[rest].second]][i]&&!row[u[rest].first][i]&&!col[u[rest].second][i]){
    57                 row[u[rest].first][i]=true;
    58                 col[u[rest].second][i]=true;
    59                 visited[block[u[rest].first][u[rest].second]][i]=true;
    60                 DFS(rest-1,sum+score[u[rest].first][u[rest].second]*i);
    61                 visited[block[u[rest].first][u[rest].second]][i]=false;
    62                 col[u[rest].second][i]=false;
    63                 row[u[rest].first][i]=false;
    64             }
    65         }
    66     }
    67 }
    68 
    69 void Initialize(){
    70 #ifndef ASC_LOCAL
    71     freopen("sudoku.in","r",stdin);
    72     freopen("sudoku.out","w",stdout);
    73 #endif
    74     int tmp;
    75     for(int i=1;i<=9;i++){
    76         for(int j=1;j<=9;j++){
    77             scanf("%d",&tmp);
    78             if(tmp==0){
    79                 unknown++;
    80                 u[unknown].first=i;
    81                 u[unknown].second=j;
    82             }
    83             else{
    84                 known+=tmp*score[i][j];
    85                 visited[block[i][j]][tmp]=true;
    86                 row[i][tmp]=true;
    87                 col[j][tmp]=true;
    88             }
    89         }
    90     }
    91 }
    Backup

     日常图包w

  • 相关阅读:
    win7下 iis配置 不能添加默认文档的 解决方案
    经典SQL语句大全
    Sql 行转列问题总结
    jQuery获取Select选择的Text和 Value(转)
    如何让虚拟目录里面的webconfig不继承网站的设置
    SQL2008 用户'sa'登录失败(错误18456)图文解决方法
    ASP.NET实现公历转农历的简单方法
    你的DNN站点慢了么?
    SQLServer2005删除log文件和清空日志的方案
    由于未能创建 Microsoft Visual C# 2008 编译器,因此未能打开项目 "xxx"
  • 原文地址:https://www.cnblogs.com/rvalue/p/7308243.html
Copyright © 2011-2022 走看看