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

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

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

刚学了DLX闲着没事去试了一下各种90、95的NOIP靶形数独,结果速度确实快了好几倍恩恩。

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std; const int MAXC = + ;
const int MAXR = + ;
const int MAXP = MAXR * + MAXC; const int p[][] = {
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,}
}; struct DLX {
int n, sz;//列数,结点总数
int sum[MAXC];//每列拥有的结点数
int row[MAXP], col[MAXP], get[MAXP];//结点所在的行和列
int left[MAXP], right[MAXP], up[MAXP], down[MAXP];//十字链表
int ans; void init(int nn) {
n = nn;
for(int i = ; i <= n; ++i) {
up[i] = down[i] = i;
left[i] = i - ; right[i] = i + ;
}
right[n] = ; left[] = n;
sz = n + ;
memset(sum, , sizeof(sum));
} void add_row(int r, int _get, vector<int> columns) {
int first = sz;
for(int i = , len = columns.size(); i < len; ++i) {
int c = columns[i];
left[sz] = sz - ; right[sz] = sz + ; down[sz] = c; up[sz] = up[c];
down[up[c]] = sz; up[c] = sz;
row[sz] = r; col[sz] = c; get[sz] = _get;
++sum[c]; ++sz;
}
right[sz - ] = first; left[first] = sz - ;
} void remove(int c) {
left[right[c]] = left[c];
right[left[c]] = right[c];
for(int i = down[c]; i != c; i = down[i])
for(int j = right[i]; j != i; j = right[j]) {
up[down[j]] = up[j]; down[up[j]] = down[j]; --sum[col[j]];
}
} void restore(int c) {
for(int i = up[c]; i != c; i = up[i])
for(int j = left[i]; j != i; j = left[j]) {
up[down[j]] = j; down[up[j]] = j; ++sum[col[j]];
}
left[right[c]] = c;
right[left[c]] = c;
} void dfs(int d, int score) {
if(right[] == ) {
ans = max(ans, score);
return ;
}
int c = right[];
for(int i = right[]; i != ; i = right[i]) if(sum[i] < sum[c]) c = i;
remove(c);
for(int i = down[c]; i != c; i = down[i]) {
for(int j = right[i]; j != i; j = right[j]) remove(col[j]);
dfs(d + , score + get[i]);
for(int j = left[i]; j != i; j = left[j]) restore(col[j]);
}
restore(c);
} int solve() {
ans = -;
dfs(, );
return ans;
}
}; DLX solver; const int SLOT = ;
const int ROW = ;
const int COL = ;
const int SUB = ; inline int encode(int a, int b, int c) {
return a * + b * + c + ;
} int puzzle[][]; void read() {
for(int i = ; i < ; ++i)
for(int j = ; j < ; ++j) scanf("%d", &puzzle[i][j]);
} int main() {
read();
solver.init();
for(int r = ; r < ; ++r)
for(int c = ; c < ; ++c)
for(int v = ; v < ; ++v)
if(puzzle[r][c] == || puzzle[r][c] == + v) {
vector<int> columns;
columns.push_back(encode(SLOT, r, c));
columns.push_back(encode(ROW, r, v));
columns.push_back(encode(COL, c, v));
columns.push_back(encode(SUB, (r/)*+c/, v));
solver.add_row(encode(r, c, v), p[r][c] * ( + v), columns);
}
printf("%d\n", solver.solve());
}

NOIP 2009 靶形数独(DLX)的更多相关文章

  1. [COGS 0407][NOIP 2009] 靶形数独

    407. [NOIP2009] 靶形数独 ★★   输入文件:sudoku.in   输出文件:sudoku.out   简单对比时间限制:5 s   内存限制:128 MB [问题描述] 小城和小华 ...

  2. [NOIp 2009]靶形数独

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

  3. 靶形数独 2009年NOIP全国联赛提高组(搜索)

    靶形数独 2009年NOIP全国联赛提高组  时间限制: 4 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description 小城和小华都是热爱数 ...

  4. 【NOIP 2009】靶形数独

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

  5. NOIp 2009:靶形数独

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

  6. 洛谷 P1074 靶形数独 Label:search 不会

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

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

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

  8. 靶形数独(codevs 1174)

    1174 靶形数独 2009年NOIP全国联赛提高组  时间限制: 4 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Descri ...

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

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

随机推荐

  1. ETO的公开赛T2《宏聚变》 题解(BY 萌萌哒123456 )

    我们注意到这道题中最多有 $(n+q)$ 个数被加入,而每个数最多被删除一次,因此每次操作 $O(logn)$的复杂度是可以接受的. 我们对于$1..100000$之间每个数分别开一个set,维护这个 ...

  2. 如何安全地跨窗体调用Timer控件 从一个窗体调用控制另外一个窗体的控件

    具体的情况是Form1中有一个Timer2时钟,Timer2时钟事件弹出Warning窗体,点击Warning窗体上面的按钮,重新激活一下Form1中的Timer2.从而实现了从一个窗体调用另外一个窗 ...

  3. linux运维、架构之路-shell编程(二)

    一.流程控制语句 1.if语句 ①if单分支:一个条件一个结果 1 2 3 4 if 条件   then      命令 fi ②if双分支:一个条件两个结果 1 2 3 4 5 6 if 条件    ...

  4. NC使用技巧

    1. NC 1.1概述 1.1.1 优点: 1)网络工具中的瑞士军刀 2)侦听模式/传输模式. 3)可代替telnet获取banner信息. 4)传输文件/目录. 5)传输文本信息. 6)加密传输文件 ...

  5. 【shell脚本学习-4】

    文本处理 #!/bin/bash#----------文本处理---------- #---------------echo----------------- # "-n":处理光 ...

  6. JDK5后的特性整理

    为了大家对JDK有一个全面的了解,下面是我从网上查找并整理了JDK5以后的所有关键新特性!(将会持续更新中) JDK5新特性 自动装箱与拆箱 枚举 静态导入 可变参数(Varargs) 内省(intr ...

  7. python应用:经纬度匹配

    需要安装第三方包:requests 本次经纬度匹配采用高德地图api,首先将gps坐标转化为高德地图的经纬度坐标,然后再根据转化后的坐标进行匹配. 本次匹配主要是获取距离给定经纬度最近的poi点地址信 ...

  8. ctf题目writeup(2)

    2019.1.29 题目地址: https://www.ichunqiu.com/battalion 1. 点开链接: include "flag.php";$a = @$_REQ ...

  9. PHP json_decode返回null解析失败原因

    在PHP5.4之前 json_decode函数有两个参数json_decode有两个参数,第一个是待解析的字符串,第二个是是否解析为Array json_decode要求的字符串比较严格:(1)使用U ...

  10. MariaDB数据库服务

    一.初始化mariaDB服务程序: yum install mariadb mariadb-server           //安装mariaDB systemctl start mariadb   ...