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
", 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
");
    else printf("%d
",ans);
    return 0;
}

最普通的正着搜  没有任何剪枝 洛谷75分

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int ans,js;

int a[10][10],hang[10][10],lie[10][10],q[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}
};

int 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} 
};


void dfs(int x,int y,int now){
//    cout<<now<<endl;
    if(x==10){
        ans=max(ans,now);
        return;
    }
    if(a[x][y]){
        if(y==9)dfs(x+1,1,now+a[x][y]*score[x][y]);
        else dfs(x,y+1,now+a[x][y]*score[x][y]);
    }else{
        for(register int i=1;i<=9;i++){
            if(hang[x][i]||lie[y][i]||q[bel[x][y]][i])continue;
            a[x][y]=i;
            hang[x][i]=lie[y][i]=q[bel[x][y]][i]=true;
            if(y==9)dfs(x+1,1,now+a[x][y]*score[x][y]);
            else dfs(x,y+1,now+a[x][y]*score[x][y]);
            a[x][y]=0;
            hang[x][i]=lie[y][i]=q[bel[x][y]][i]=false;
        }
    }
}
        
int main(){
    for(int i=1;i<=9;i++){
        for(int j=1;j<=9;j++){
            scanf("%d",&a[i][j]);
            if(a[i][j]){
                hang[i][a[i][j]]=true;
                lie[j][a[i][j]]=true;
                q[bel[i][j]][a[i][j]]=true;
            }
        }
    }
    dfs(1,1,0);
    printf("%d
",(ans==0?-1:ans));
    return 0;
} 
原文地址:https://www.cnblogs.com/zzyh/p/7654458.html