NOIP2009 靶形数独(搜索)

以前做过一道hdu类似的数独题,那道题我没有加什么优化就过了,然后这道题不加优化可以得50~80分,要上80分就必须要优化

可以用位运算保存每一行每一列每个九宫格内已经使用的数,例如userow[i] = 011101111表示第i行还有1,5两个数字没有使用,那么我们枚举每个未知的格子(i,j)时,他不能填的数就是userow[i]|usecol[j]|usebox[i/3*3+j/3] ,其实这样做也不能优化什么时间,下面才是最NB的优化

在输入的时候我们可以统计每一行已知的数,于是我们能够把没有填数的格子按每一行从小到大来排序,这样,枚举这个点能够扩展出来的搜索树就会比原来小。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define RE ((1<<9)-1)
using namespace std;
int sum_a[10];
struct T
{
    int x,y;
    bool operator < (T t) const//已知数多的放在前面
    {
        if(sum_a[x] == sum_a[t.x])
            return x < t.x;
        return sum_a[x] > sum_a[t.x];
    }
}unknown[100];//保存没有填的格子的位置
int st[10][10];
int p[10][10];//权值数组
void init()
{
    for(int i = 0; i < 9; i++)
    {
        p[0][i] = p[8][i] = p[i][0] = p[i][8] = 6;
    }
    for(int i = 1; i < 8; i++)
    {
        p[1][i] = p[7][i] = p[i][1] = p[i][7] = 7;
    }
    for(int i = 2; i < 7; i++)
    {
        p[2][i] = p[6][i] = p[i][2] = p[i][6] = 8;
    }
    for(int i = 3; i < 6; i++)
    {
        p[3][i] = p[5][i] = p[i][3] = p[i][5] = 9;
    }
    p[4][4] = 10;
}
int ans = -1;
int cnt,sorce;
int userow[10];//每一行使用的数
int usecol[10];//每一列使用的数
int usebox[10];//每一个九宫格内使用的数
void dfs(int cur)
{
    if(cur > cnt)
    {
        ans = max(sorce,ans);
        return;
    }
    int x = unknown[cur].x;
    int y = unknown[cur].y;
    int temp = (userow[x]|usecol[y]|usebox[x/3*3+y/3]);
    if(temp == RE) return;//没有可以使用的数
    for(int i = 1; i <= 9; i++)
    if(!((temp>>(i-1))&1))
    {
        st[x][y] = i;
        usebox[x/3*3+y/3] |= (1<<(i-1));
        userow[x] |= (1<<(i-1));
        usecol[y] |= (1<<(i-1));
        sorce += st[x][y]*p[x][y];
        dfs(cur+1);
        sorce -= st[x][y]*p[x][y];
        st[x][y] = 0;
        usebox[x/3*3+y/3] ^= (1<<(i-1));
        userow[x] ^= (1<<(i-1));
        usecol[y] ^= (1<<(i-1));
    }
}
int main()
{
    //freopen("sudoku.in","r",stdin);
    //freopen("sudoku.out","w",stdout);
    init();
    for(int i = 0; i < 9; i++)
    {
        for(int j = 0; j < 9; j++)
        {
            scanf("%d",&st[i][j]);
            if(st[i][j] != 0)
            {
                sorce += st[i][j]*p[i][j];
                userow[i] |= (1<<(st[i][j]-1));
                usecol[j] |= (1<<(st[i][j]-1));
                usebox[i/3*3+j/3] |= (1<<(st[i][j]-1));
                ++sum_a[i];//统计i行已知的数
            }
        }
    }
    for(int i = 0; i < 9; i++)
        for(int j = 0; j < 9; j++)
        {
            if(!st[i][j])
            {
                ++cnt;
                unknown[cnt].x = i;
                unknown[cnt].y = j;
            }
        }
    sort(unknown+1,unknown+cnt+1);
    dfs(1);
    printf("%d\n",ans);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-19 18:25:29

NOIP2009 靶形数独(搜索)的相关文章

[NOIP2009] 靶形数独

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

[NOIP2009]靶形数独 题解

407. [NOIP2009] 靶形数独 ★★   输入文件:sudoku.in   输出文件:sudoku.out   简单对比时间限制:5 s   内存限制:128 MB [问题描述] 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格

[NOIP2009] 靶形数独(搜索+剪枝)

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

[NOIP2009]靶形数独 深搜+枝杈优化

这道题,又是一位玄学搜索...... 我是用的蜗牛序搜的(顾名思义,@,这么搜),我正着搜80然后一反转比原来快了几十倍........一下AC....... 我的思路是这样的话我们可以从内到外或者从外到内搜索,这样的话我们就可以在一定程度上运用贪心,因为中间的价值大外面的价值小,我是作为一个从来没有玩过数独的人的思路...然而任何一个玩过数独的人都会先选可能状态少的优先搜索....... 对于这题里的数据,可行方案很少因此摆在我们面前的不是减去不优的解而是减去不成立的解,然而对于不成立的解在我

【NOIP2009】靶形数独 DLX(Dancing Links)

[NOIP2009]靶形数独 T4 Time Limit: 2 Sec  Memory Limit: 128 MB Description 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向Z 博士请教,Z 博士拿出了他最近发明的"靶形数独",作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有9 个3 格宽×3 格高的小九宫格(用粗黑色线隔开的).在

【NOIP2009】靶形数独

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

靶形数独 (codevs 1174)题解

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

洛谷 P1074 靶形数独

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

NOIP提高组 2009 靶形数独 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 此题解目前在洛谷上无法AC,只能拿到95分,使用洛谷的朋友请注意. 题目链接:  洛谷   CODEVS  Vijos 描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教, Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9