CODEVS 1174 靶形数独

Posted 小时のblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CODEVS 1174 靶形数独相关的知识,希望对你有一定的参考价值。

题目描述 Description

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他
们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向Z 博士请教,
Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。
靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有9 个3 格宽×3 格
高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些

数字,利用逻辑推理,在其他的空格上填入1 到9 的数字。每个数字在每个小九宫格内不能
重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即
每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。

 

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

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

技术分享
输入描述 Input Description

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

输出描述 Output Description

输出可以得到的靶形数独的最高分数。如果这个数独无解,则输出整数-1。

样例输入 Sample Input

【输入输出样例 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

样例输出 Sample Output

【输入输出样例 1】

2829

【输入输出样例 1】

2852

数据范围及提示 Data Size & Hint

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

 

题解:爆搜

记录0的位置 只填0 卡时

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include<iostream>
using namespace std;

int block_index[10][10] = {{0},
    {0, 1, 1, 1, 2, 2, 2, 3, 3, 3},
    {0, 1, 1, 1, 2, 2, 2, 3, 3, 3},
    {0, 1, 1, 1, 2, 2, 2, 3, 3, 3},
    {0, 4, 4, 4, 5, 5, 5, 6, 6, 6},
    {0, 4, 4, 4, 5, 5, 5, 6, 6, 6},
    {0, 4, 4, 4, 5, 5, 5, 6, 6, 6},
    {0, 7, 7, 7, 8, 8, 8, 9, 9, 9},
    {0, 7, 7, 7, 8, 8, 8, 9, 9, 9},
    {0, 7, 7, 7, 8, 8, 8, 9, 9, 9}
};

int value[10][10] = {{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[10][10];
int pos[101][2];       ////zeros
bool line[10][10], row[10][10], block[10][10];  //vis
int res = -1;
int times;

void dfs(int zeros, int sum)
{
    if(!zeros)
    {
        if(sum > res)res = sum;
        return;
    }
    if(times++ > 8000000)return;
    int i = pos[zeros][0], j = pos[zeros][1];
    for(int k = 1; k <= 9; k++)  //place number
    {
        if(!line[i][k] && !row[j][k] && !block[block_index[i][j]][k])
        {
            line[i][k] = row[j][k] = block[block_index[i][j]][k] = true;
            dfs(zeros - 1, sum + k * value[i][j]);
            line[i][k] = row[j][k] = block[block_index[i][j]][k] = false;
        }
    }
}

int main()
{
    int tot = 0;
    int zeros = 0;
    for(int i = 1; i <= 9; i++)
    {
        for(int j = 1; j < 10; j++)
        {
            int vvv;
            scanf("%d", &vvv);
            if(map[i][j] = vvv)
            {
                line[i][vvv] = row[j][vvv] = block[block_index[i][j]][vvv] = 1;
                tot += vvv * value[i][j];
            }else
            {
                zeros++;
                pos[zeros][0] = i;
                pos[zeros][1] = j;
            }
        }
    }
    dfs(zeros, tot);
    printf("%d\n", res? res: -1);
    return 0;
}

 

挨个填..洛谷只能95分,codevs上A了,因为codevs的时限是4s...洛谷1s....

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<algorithm>
using namespace std;
int cnt,ans,map[10][10],row[10][10],col[10][10],cub[10][10];
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
},
bel[10][10]={
0,0,0,0,0,0,0,0,0,0,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9
};

inline int read(){
    char ch=getchar();int x=0,f=1;
    for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-0;
    return x*f;
}

void dfs(int x,int y,int sum){
    if(x==0){
        if(sum>ans)ans=sum;
        return;
    }
    if(map[x][y]){
        if(y==1)dfs(x-1,9,sum+map[x][y]*score[x][y]);
        else dfs(x,y-1,sum+map[x][y]*score[x][y]);
    }
    for(register int i=1;i<=9;i++){
        if(row[x][i]==0&&col[y][i]==0&&cub[bel[x][y]][i]==0){
            row[x][i]=col[y][i]=cub[bel[x][y]][i]=true;
            int cnt=sum+score[x][y]*i;
            if(y==1)dfs(x-1,9,cnt);
            else dfs(x,y-1,cnt);
            row[x][i]=col[y][i]=cub[bel[x][y]][i]=false;
        }
    }
}

int main(){
    for(register int i=1;i<=9;i++){
        for(int j=1;j<=9;j++){
           int x;
            x=read();
            map[i][j]=x;
            if(x){
                row[i][x]=true;
                col[j][x]=true;
                cub[bel[i][j]][x]=true;
            }
        }
    }
    ans=-1;
    dfs(9,9,0);
    if(ans<0)printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}

 

 


































以上是关于CODEVS 1174 靶形数独的主要内容,如果未能解决你的问题,请参考以下文章

code1174 靶形数独

[NOIP2009提高组]靶形数独

NOIP提高组 2009 靶形数独 题解

[NOIP2009] 靶形数独

NOIP2009靶形数独

[NOIP2009]靶形数独 题解