zoukankan      html  css  js  c++  java
  • NOIP2009靶形数独

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



    28.png


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

    29.png
    由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的高分数。
    输入
    输入一共 9 行。每行 9个整数(每个数都在 
    0—9 的范围内),表示一个尚未填满的数独方格,未填的空格用 0 表示。每两个数字之间用一个空格隔开。
    输出
    输出共 1 行。

    输出可以得到的靶形数独的高分数。如果这个数独无解,则输出整数 −1 。
    输入示例
    样例输入 1
    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
    样例输入 2
    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 
    输出示例
    样例输出 1
    2829
    样例输出 2
    2852

    因为我们知道分值是多少,所以可以先打出表格,然后美剧所有的情况,进行判断,最后加点剪枝就可以过

    难点在于如何计算出每个数字在哪个宫,(x-1)/3*3+1+(y-1)/3,x代表行,y代表列

    还有就是我们OJ是真的慢,最后只好打表QAQ

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<queue>
    using namespace std;
    inline int min(int a,int b){return a<b?a:b;}
    inline int max(int a,int b){return a>b?a:b;}
    inline int rd()
    {
        int x=0,f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    inline void write(int x)
    {
         if(x<0) putchar('-'),x=-x;
         if(x>9) write(x/10);
         putchar(x%10+'0');
    }
    const int score[10][10]={{0,0,0,0,0,0,0,0,0,0},
                            {0,6,6,6,6,6,6,6,6,6},
                            {0,6,7,7,7,7,7,7,7,6},
                            {0,6,7,8,8,8,8,8,7,6},
                            {0,6,7,8,9,9,9,8,7,6},
                            {0,6,7,8,9,10,9,8,7,6},
                            {0,6,7,8,9,9,9,8,7,6},
                            {0,6,7,8,8,8,8,8,7,6},
                            {0,6,7,7,7,7,7,7,7,6},
                            {0,6,6,6,6,6,6,6,6,6}};
    int map[100][100],row[100][100],col[100][100],gong[100][100];
    int rcnt[10000],ccnt[10000];
    int cnt=0;
    int ans=-1;
    int id(int x,int y){return (x-1)/3*3+1+(y-1)/3;}
    int check()
    {
        int sum=0;
        for(int i=1;i<=9;i++) for(int j=1;j<=9;j++) sum+=(score[i][j]*map[i][j]);
        return sum;
    }
    void dfs(int r,int c,int sum)
    {
        if(sum==81)
        {
            ans=max(ans,check());
            return ;
        }
        for(int k=1;k<=9;k++)
        {
            if(row[r][k]!=0||col[c][k]!=0||gong[id(r,c)][k]!=0) continue;
            row[r][k]=1;
            col[c][k]=1;
            gong[id(r,c)][k]=1;
            rcnt[r]++;
            ccnt[c]++;
            map[r][c]=k;
            int rr,tmpr=-1,cc,tmpc=-1;
            for(int j=1;j<=9;j++)
            {
                if(rcnt[j]>tmpr&&rcnt[j]<9)
                {
                    tmpr=rcnt[j];
                    rr=j;
                }
            }
            for(int j=1;j<=9;j++)
            {
                if(ccnt[j]>tmpc&&map[rr][j]==0)
                {
                    tmpc=ccnt[j];
                    cc=j;
                }
            }
            dfs(rr,cc,sum+1);
            row[r][k]=0;
            col[c][k]=0;
            gong[id(r,c)][k]=0;
            map[r][c]=0;
            rcnt[r]--;
            ccnt[c]--;
        }
        return ;
    }
    int main()
    {
        int i,j;
        for(i=1;i<=9;i++)
        {
            for(j=1;j<=9;j++)
            {
                map[i][j]=rd();
                if(map[i][j]!=0)
                {
                    row[i][map[i][j]]=1;
                    col[j][map[i][j]]=1;
                    gong[id(i,j)][map[i][j]]=1;
                    rcnt[i]++;
                    ccnt[j]++;
                    cnt++;
                }
            }
        }
        int r,tmpr=-1,c,tmpc=-1;
        for(i=1;i<=9;i++)
        {
            if(rcnt[i]>tmpr&&rcnt[i]<9)
            {
                tmpr=rcnt[i];
                r=i;
            }
        }
        for(i=1;i<=9;i++)
        {
            if(ccnt[i]>tmpc&&map[r][i]==0)
            {
                tmpc=ccnt[i];
                c=i;
            }
        }
        dfs(r,c,cnt);
        printf("%d",ans);
        return 0;
    }
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    java (java.exe) 解释器 -D 选项
    Ubuntu 12.04.3 X64 使用 NFS 作为文件共享存储方式 安装 Oracle11g RAC
    Ubuntu下 Oracle sqldeveloper中文目录、文件,select查询结果中:中文乱码
    行测题型
    Left join on where 区别
    常见公文——决定和请示
    宜家沙发测评
    "放管服"改革 清单
    shell && and ||
    ORA-01722: invalid number
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9755383.html
Copyright © 2011-2022 走看看