https://www.luogu.org/problemnew/show/P1074

显然是dfs 而且没有什么剪枝记忆化之类的 但是预处理比较麻烦

我用三个二维数组存状态:visx[x][i]代表x行有没有选 i 这个数   visy[y][i]代表y列有没有选 i    visg[g][i]代表第g个九宫格有没有选i

当遍历的时候 发现visx[x][i]==0&&visy[y][i]==0&&visg[g][i]==0 说明 i 还没有被选 就可以向下dfs

至于遍历的顺序 我们玩数独的时候都知道 肯定先从已知点比较多的地方开始考虑

比如 第一行:7 0 0 9 0 0 0 0 1 有6个位置未知

第九行:0 8 0 5 0 4 0 1 2 只有4个位置未知 那么我们肯定先考虑第九行

所以只需要把行sort排序一下 调整一下遍历的顺序即可

不过排序又引申出来一个问题 就是我们不知道排序之后的第一行 原来是第几行 为了解决这个问题 我们可以用一个结构体存储每一行有几个未知位置:

typedef struct
{
int nums=; //未知位置数量
int x; //行数
}node;

最后 我们需要维护一个一维数组,用来保存修正后的遍历的序列(当然二维也可以)

最后的的最后 每找到一组数独的解 都要更新最大值

具体看代码吧:

#include<bits/stdc++.h>

using namespace std;

typedef struct
{
int nums=;
int x;
}node;
node e[]; int m[][],anss,u,visx[][],visy[][],visg[][],q[],pre,flag;
int s[][]={,,,,,,,,,,, //保存每个位置上的分数 比较懒 直接打表了
,,,,,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,}; bool cmp(node a,node b)
{
return a.nums<b.nums;
} void dfs(int t)
{
int i,j;
if(t==u+)
{
flag=;
int p=;
for(i=;i<=;i++)
for(j=;j<=;j++)
p+=m[i][j]*s[i][j];
anss=max(anss,p); //更新最大值
return;
}
int x=(q[t]-)/+;
int y=q[t]-(x-)*;
int g=((x-)/)*+(y-)/+;
for(i=;i<=;i++)
{
if(visx[x][i]==&&visy[y][i]==&&visg[g][i]==)
{
visx[x][i]=;
visy[y][i]=;
visg[g][i]=;
m[x][y]=i;
dfs(t+);
visx[x][i]=;
visy[y][i]=;
visg[g][i]=;
}
}
} int main()
{
int i,j;
for(i=;i<=;i++)
e[i].x=i;
for(i=;i<=;i++)
for(j=;j<=;j++)
{
scanf("%d",&m[i][j]);
if(m[i][j]==)
e[i].nums++;
else
{
pre+=m[i][j]*s[i][j];
visx[i][m[i][j]]=;
visy[j][m[i][j]]=;
int g=((i-)/)*+(j-)/+; //计算当前点属于哪一个九宫格
visg[g][m[i][j]]=;
}
}
sort(e+,e+,cmp);
for(i=;i<=;i++)
for(j=;j<=;j++)
{
if(m[e[i].x][j]==)
{
int nums=(e[i].x-)*+j; //如果当前位置未知,把他放入准备遍历的序列里
q[++u]=nums; //u记录了有多少点未知
}
}
dfs();
if(flag==) //如果无解
{
cout<<-<<endl;
return ;
}
cout<<anss<<endl; }

P1074 靶形数独 dfs+预处理的更多相关文章

  1. P1074 靶形数独 dfs回溯法

    题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶 ...

  2. P1074 靶形数独

    P1074 靶形数独正着搜80分,完全倒置95分,完全倒置后左右再倒置,就会A掉,到时候脑洞要大一些. #include<iostream> #include<cstdio> ...

  3. 洛谷——P1074 靶形数独

    P1074 靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z ...

  4. P1074 靶形数独题解

    题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶 ...

  5. 洛谷P1074 靶形数独 [搜索]

    题目传送门 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了 ...

  6. NOIP2009靶形数独[DFS 优化]

    描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独 ...

  7. [洛谷P1074] 靶形数独

    洛谷题目链接:靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博 ...

  8. 洛谷 P1074 靶形数独

    题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的 ...

  9. [NOIP2009] 提高组 洛谷P1074 靶形数独

    题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的 ...

随机推荐

  1. springMVC项目访问URL链接时遇到某一段然后忽略后面的部分

    背景:一个链接URL:http:localhost/tq/asf/218732,配置URL使遇到/asf后直接跳转不识别/asf后面的218732 因为是在ssm框架下做的项目,所以用spring的注 ...

  2. LOJ-6280-数列分块入门4

    链接: https://loj.ac/problem/6280 题意: 给出一个长为n 的数列,以及 n个操作,操作涉及区间加法,区间求和. 思路: sum维护区间和, tag维护每个区间多加的,不是 ...

  3. 【shell】文本匹配问题

    原文本通过TITLE分段 TITLE1 xxx yyy TITLE2 xxx yyy hello zzz hello TITLE3 xxx hello 类似于这样的,hello可能有多个,需要打印出含 ...

  4. php7魔术方法

    抽空把php7的魔术方法复习一下,大致如下 __constract:在实例化一个类时,触发 __destruct:在一个实例对象被销毁的时候触发 __set(string $name , mixed ...

  5. Mysql 日期函数date_format()

    用法:DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据 1.语法 date_fromat(date,format) 说明:date 参数是合法的日期.format 规定日期/时间的输 ...

  6. ps -aux显示信息COMMAND不全

    ps -aux结果: ps -auxwww结果:

  7. BZOJ 2121: 字符串游戏 区间DP + 思维

    Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对 于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删 ...

  8. [luogu]P2657低头一族[树状数组]

    [luogu]P2657 低头一族 题目描述 一群青年人排成一队,用手机互相聊天. 每个人的手机有一个信号接收指标,第i个人的接收指标设为v[i]. 如果位置在x[i]的人要和位置在xj的人聊天,那么 ...

  9. Vue(核心思想)

    1.Es6语法普及 let和var的区别: var:定义变量时,在全局范围内都有效;所以在变量没有声明之前就能使用,值为undefined, 称为变量提升; let:声明的变量一定要在声明后使用,而且 ...

  10. linux文件夹目录含义及用途

    /boot,存放linux启动文件和内核: /initrd,boot loader initialized RAM disk,就是由boot loader初始化的内存盘.在linux内核启动前,boo ...