洛谷OJ 1074 靶型sudoku dfs(搜索顺序优化)

https://www.luogu.org/problem/show?pid=1074

题意:靶型sudoku 问填完的最大得分?
//优化:从可能性小的开始搜索,把地图分数设置成常量数组,接着暴力即可

#include <bits/stdc++.h>
using namespace std;
const int N=2e2+20;
int row[N][N],col[N][N],vis[N][N];//row[i][1~9] 第i列是否能选j
int a[N][N];
int ans,n=9,cnt;
int dist(int x,int y)
{
    return (x/3)*3+(y/3);
}
bool check(int x,int y,int k)
{
    if(row[x][k]||col[y][k])
        return false;
    if(vis[dist(x,y)][k])
        return false;
    return true;
}
int b[][9]={
{6,6,6,6,6,6,6,6,6},
{6,7,7,7,7,7,7,7,6},
{6,7,8,8,8,8,8,7,6},
{6,7,8,9,9,9,8,7,6},
{6,7,8,9,10,9,8,7,6},
{6,7,8,9,9,9,8,7,6},
{6,7,8,8,8,8,8,7,6},
{6,7,7,7,7,7,7,7,6},
{6,6,6,6,6,6,6,6,6},
};
struct node{
    int x,y;
};
node getnext()  //找到可能性小的
{
    node tmp;
    int min,t;
    tmp.x=n;
    tmp.y=n;
    min=n;
    for (int i=0;i<9;i++)
        for (int j=0;j<9;j++)
            if(!a[i][j])
            {
                t=0;
                for (int k=1;k<=9;k++)
                    if (!row[i][k])
                        if (!col[j][k])
                            if (!vis[dist(i,j)][k])
                                t++;
                if (t<min)
                {
                    min=t;
                    tmp.x=i;
                    tmp.y=j;
                }
            }
    return tmp;
}
void dfs(int p)
{
    if(p>=cnt)//需要填cnt个
    {
        int res=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                res+=b[i][j]*a[i][j];
        ans=max(ans,res);
        return;
    }
    node tmp=getnext();
    if(tmp.x==n&&tmp.y==n)
        return;
    int x=tmp.x,y=tmp.y;
    for(int k=1;k<=9;k++)
    {
        if(check(x,y,k))
        {
            row[x][k]=col[y][k]=vis[dist(x,y)][k]=1;
            a[x][y]=k;
            dfs(p+1);
            row[x][k]=col[y][k]=vis[dist(x,y)][k]=0;
            a[x][y]=0;
        }
    }
}
int main()
{
    int n=9;
    ans=-1;
    cnt=n*n;
    memset(vis,0,sizeof(vis));
    memset(col,0,sizeof(col));
    memset(row,0,sizeof(row));
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<9;j++)
        {
            scanf("%d",&a[i][j]);
            if(a[i][j])
            {
                row[i][a[i][j]]=1;
                col[j][a[i][j]]=1;
                vis[dist(i,j)][a[i][j]]=1;
                cnt--;//
            }
        }
    }
    dfs(0);
    cout<<ans<<endl;
    return 0;
} 
时间: 2024-10-24 02:39:43

洛谷OJ 1074 靶型sudoku dfs(搜索顺序优化)的相关文章

洛谷OJ 1433 吃奶酪 暴力dfs(最优性cut)

https://www.luogu.org/problem/show?pid=1433 题意:起点为(0,0) 有n个点 求出起点出发经过n个点的最小距离//15个点 暴力 + 最优性cut(sum+还剩的点*最小距离>=ans 则stop) 水过... #include <bits/stdc++.h> using namespace std; typedef pair<int,double> pii; const int N=2e3+20; const double inf

洛谷OJ P1074 靶形数独 解题报告

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

洛谷OJ P1141 01迷宫 解题报告

洛谷OJ P1141 01迷宫 解题报告 by MedalPluS [题目描述]    有一个仅由数字0与1组成的n×n格迷宫.若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上.你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身).   [输入描述]   输入的第1行为两个正整数n,m.  下面n行,每行n个字符,字符只可能是0或者1,字符之间没有空格.  接下来m行,每行2个用空格分隔的正整数i,j,对

洛谷OJ P1433 吃奶酪 解题报告

洛谷OJ P1433 吃奶酪 解题报告 by MedalPluS 题目描述 房间里放着n块奶酪.一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处. 输入描述 第一行一个数n  (n<=15)接下来每行2个实数,表示第i块奶酪的坐标.两点之间的距离公式=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) 输出描述 一个数,表示要跑的最少距离,保留2位小数. 分析 这题很明显就是一个搜索题,枚举一下1_n的全排列,然后从0开始,按照排列一个一个算,时间

洛谷OJ P1045 麦森数 解题报告

洛谷OJ P1045 麦森数 解题报告 by MedalPluS   题目描述 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示)   输入描述   文件中只包含一个整数P(1000&l

洛谷OJ P1379 八数码难题 解题报告

洛谷OJ P1379 八数码难题 解题报告 by MedalPluS 题目描述   在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变.   输入格式   输入初试状态,一行九个数字,空格用0表示   输出格式 只有一行,该行只有一个数字,表示从初始状态到

洛谷OJ P1032 字串变换 解题报告

洛谷OJ P1032 字串变换 解题报告 by MedalPluS   [题目描述] 已知有两个字串 A$, B$ 及一组字串变换的规则(至多6个规则): A1$ -> B1$ A2$ -> B2$ 规则的含义为:在 A$中的子串 A1$ 可以变换为 B1$.A2$ 可以变换为 B2$ …. 例如:A$='abcd' B$='xyz' 变换规则为: ‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’ 则此时,A$ 可以经过一系列的变换变为 B$,其变换的过程为:

洛谷OJ P1010 幂次方 解题报告

洛谷OJ P1010 幂次方 解题报告 by MedalPluS 题目描述   任何一个正整数都可以用2的幂次方表示.例如        137=2^7+2^3+2^0         同时约定方次用括号来表示,即a^b 可表示为a(b).由此可知,137可表示为:        2(7)+2(3)+2(0)进一步:7= 2^2+2+2^0   (21用2表示)        3=2+20   所以最后137可表示为:        2(2(2)+2+2(0))+2(2+2(0))+2(0)又如

洛谷OJ P1126 机器人搬重物 解题报告

洛谷OJ P1126 机器人搬重物 解题报告 by MedalPluS [题目描述]    机器人移动学会(RMI)现在正尝试用机器人搬运物品.机器人的形状是一个直径1.6米的球.在试验阶段,机器人被用于在一个储藏室中搬运货物.储藏室是一个N*M的网格,有些格子为不可移动的障碍.机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方.机器人接受的指令有:向前移动1步(Creep):向前移动2步(Walk):向前移动3步(Run):向左转(Left):向右转(Right).