NOIP2009 靶形数独
4.靶形数独
(sudoku.pas/c/cpp)
【问题描述】
小城和小华都是热爱数学的好学生, 近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,
Z 博士拿出了他 近发明的“靶形数独”,作为这两个孩子比试的题目。
靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9 的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)
上图具体的分值分布是: 里面一格(黄色区域)为 10 分,黄色区域外面的一圈(红色区域)每个格子为 9 分,再外面一圈(蓝色区域)每个格子为 8 分,蓝色区域外面一圈(棕色区域)每个格子为 7 分, 外面一圈(白色区域)每个格子为 6 分,如上图所示。比赛的要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法),而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 2829。游戏规定,将以总分数的高低决出胜负。
由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的 高分数。
【输入】
输入文件名为 sudoku.in。
一共 9 行。每行 9 个整数(每个数都在 0—9 的范围内),表示一个尚未填满的数独方格,未填的空格用“0”表示。每两个数字之间用一个空格隔开。
【输出】
输出文件 sudoku.out 共 1 行。
输出可以得到的靶形数独的 高分数。如果这个数独无解,则输出整数-1。
【输入输出样例 1】
sudoku.in |
sudoku.out |
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 |
2829 |
【输入输出样例 2】
sudoku.in |
sudoku.out |
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 |
2852 |
【数据范围】
40%的数据,数独中非 0 数的个数不少于 30。 80%的数据,数独中非 0 数的个数不少于 26。
100%的数据,数独中非 0 数的个数不少于 24。
【思路】
Dancing Links X
这道题用搜索做只过了80分。
很多人提到可以用DLX算法求解数独,在下还没有理解这里只贴一个别人的代码:
【搜索_80】
- #include<iostream>
- #include<algorithm>
- #include<vector>
- #define FOR(a,b,c) for(int a=(b);a<(c);a++)
- using namespace std;
- const int maxn = +;
- const int N=;;
- struct Node{
- int x,y;
- Node(const int x,const int y) {
- this->x=x; this->y=y;
- }
- vector<int> can;
- bool operator <(const Node& rhs) const{
- return can.size()<rhs.can.size(); //?ù?Y?é??μ?êy×??àéù′óD?μ?′ó??Dò
- }
- };
- vector<Node> nodes;
- int R[maxn][maxn],C[maxn][maxn],S[maxn][maxn];
- int vis[maxn][maxn];
- int ans=-;
- inline int ID(int i,int j) { return (i/)*+(j/); }
- inline int score(int i,int j,int k) {
- if(i== && j==) return *k;
- if(i>= && i<= && j>= && j<=) return *k;
- if(i>= && i<= && j>= && j<=) return *k;
- if(i>= && i<= && j>= && j<=) return *k;
- return *k;
- }
- inline int jisuan(int x,int y) {
- if(vis[x][y]) return (<<);
- int res=;
- for(int i=;i<N;i++) {
- //if(vis[x][i]) res++;
- //if(vis[i][y]) res++;
- }
- for(int i=;i<N;i++) if(S[ID(x,y)][i]) res++;
- return res;
- }
- int nc;
- void dfs(int d,int sum) {
- if(d==nc){
- ans=max(ans,sum);
- return ; //
- }
- int _max=(<<),_maxi;
- for(int i=;i<nc;i++) {
- int tmp=jisuan(nodes[i].x,nodes[i].y);
- if(tmp<_max) {
- _max=tmp;
- _maxi=i;
- }
- }
- int x=nodes[_maxi].x , y=nodes[_maxi].y;
- FOR(j,,nodes[_maxi].can.size()) {
- int i=nodes[_maxi].can[j];
- if((R[x][i])||(C[y][i])||(S[ID(x,y)][i])) continue;
- R[x][i]=C[y][i]=S[ID(x,y)][i]=; vis[x][y]=;
- dfs(d+,sum+score(x,y,i));
- R[x][i]=C[y][i]=S[ID(x,y)][i]=; vis[x][y]=;
- }
- }
- int main() {
- ios::sync_with_stdio(false);
- int x;
- int sum=;
- FOR(i,,N) FOR(j,,N) {
- cin>>x;
- if(x==) nodes.push_back(Node(i,j)); //???????′ì?μ?μ?
- else {
- vis[i][j]=;
- R[i][x]=C[j][x]=S[ID(i,j)][x]=;
- sum+= score(i,j,x); //±eíüá?í3???-à′μ?·?êy
- }
- }
- for(int i=;i<nodes.size();i++){
- int x=nodes[i].x,y=nodes[i].y;
- for(int j=;j<=;j++) if((!R[x][j])&&(!C[y][j])&&(!S[ID(x,y)][j])) nodes[i].can.push_back(j);
- }
- nc=nodes.size();
- dfs(,sum);
- cout<<ans;
- return ;
- }
【DLX_AC】
- #include <stdio.h>
- #include <stdlib.h>
- #define con(i) (1 << (i))
- #define getid(i, j) ((i) / 3 * 3 + (j) / 3)
- #define getidorder(i, j) (3 * ((i) - (i) / 3 * 3) + (j) - (j) / 3 * 3)
- int map[][];
- int row[];
- int n_row[], n_line[];
- int small[];
- int f[];
- int ans;
- int sore[][] = { {, , , , , , , , },
- {, , , , , , , , },
- {, , , , , , , , },
- {, , , , , , , , },
- {, , , , , , , , },
- {, , , , , , , , },
- {, , , , , , , , },
- {, , , , , , , , },
- {, , , , , , , , } };
- void getgrade(void)
- {
- int i, j;
- int t = ;
- for(i = ; i < ; i++){
- for(j = ; j < ; j++){
- t += map[i][j] * sore[i][j];
- }
- }
- if(ans < t){
- ans = t;
- }
- }
- int so[], count[];
- int end;
- void srch(int now)
- {
- int i, j, p;
- int pos, k;
- if(now == ){
- getgrade();
- return;
- }
- i = so[now];
- if(count[i] == ){
- srch(now + );
- return;
- }
- count[i]--;
- p = ^ row[i];
- p = p & -p;
- row[i] |= p;
- j = f[p];
- pos = ^ (n_row[i] | n_line[j] | small[getid(i, j)]);
- while(pos > ){
- k = pos & -pos;
- pos ^= k;
- n_row[i] |= k;
- n_line[j] |= k;
- small[getid(i, j)] |= k;
- map[i][j] = f[k] + ;
- srch(now);
- n_row[i] ^= k;
- n_line[j] ^= k;
- small[getid(i, j)] ^= k;
- }
- count[i]++;
- row[i] ^= p;
- }
- int main(int argc, char **argv)
- {
- int i, j, t;
- for(i = , j = ; i <= ; i <<= , j++){
- f[i] = j;
- }
- for(i = ; i < ; i++){
- for(j = ; j < ; j++){
- scanf("%d", &map[i][j]);
- if(map[i][j] != ){
- row[i] |= con(j);
- t = con(map[i][j] - );
- if(((n_row[i] & t) != ) || ((n_line[j] & t) != ) || ((small[getid(i, j)] & t) != )){
- printf("-1\n");
- return ;
- }
- n_row[i] |= t;
- n_line[j] |= t;
- small[getid(i, j)] |= t;
- }else{
- count[i]++;
- }
- }
- }
- for(i = ; i < ; i++){
- so[i] = i;
- }
- for(i = ; i < ; i++){
- for(j = i + ; j < ; j++){
- if(count[so[i]] > count[so[j]]){
- so[i] ^= so[j];
- so[j] ^= so[i];
- so[i] ^= so[j];
- }
- }
- }
- for(i = ; count[so[i]] == ; i++){ ; }
- srch(i);
- if(ans == ){
- printf("-1\n");
- return ;
- }
- printf("%d\n", ans);
- return ;
- }
NOIP2009 靶形数独的更多相关文章
- NOIP2009靶形数独[DFS 优化]
描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独 ...
- [NOIP2009]靶形数独 题解
407. [NOIP2009] 靶形数独 时间限制:5 s 内存限制:128 MB [问题描述] 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低. ...
- [NOIP2009] 靶形数独(搜索+剪枝)
题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的 ...
- NOIP2009靶形数独
题目描述: 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“ ...
- [NOIP2009] 靶形数独(搜索)
P1074 靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士 ...
- NOIP2009靶形数独(暴搜)
题目传送门 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向Z博士请教,Z博士拿出了他最近发明 ...
- Vijos1775 CodeVS1174 NOIP2009 靶形数独
靶形数独 描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教, Z 博士拿出了他最近发 ...
- [NOIP2009] 靶形数独 骚气的大爆搜
这两天OD留的题是搜索,这个东西,就是历年的NOIP压轴题嘛.做了几道什么斗地主啊啥的,感觉还是这题我还懂点. 这道题的搜(xia)索(da)思路是这样的:预处理出一切能处理的东西. 数独大家都了解吧 ...
- [NOIP2009]靶形数独 深搜+枝杈优化
这道题,又是一位玄学搜索...... 我是用的蜗牛序搜的(顾名思义,@,这么搜),我正着搜80然后一反转比原来快了几十倍........一下AC....... 我的思路是这样的话我们可以从内到外或者从 ...
随机推荐
- 2038: [2009国家集训队]小Z的袜子(hose) - BZOJ
Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只 ...
- Netty4.x中文教程系列(二) – 白话概念
"Hello World"的代码固然简单,不过其中的几个重要概念(类)和 Netty的工作原理还是需要简单明确一下,至少知道其是负责什.方便自己以后更灵活的使用和扩展. 声明, ...
- ExtJS4.2学习(11)可拖放的表格(转)
鸣谢:http://www.shuyangyang.com.cn/jishuliangongfang/qianduanjishu/2013-11-18/180.html --------------- ...
- Deployment of VC2008 apps without installing anything
If you create a default CRT/MFC application with VS2008, this application will not run on other comp ...
- STL,ATL,WTL之间的联系和区别
STL即 Standard Template Library (标准模板库) STL是惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R M ...
- BZOJ 3925 ZJOI2015 地震后的幻想乡
假设我们用了边权前i小的边使得图连通,那么对答案的贡献为i/m+1 又因为期望的线性性质,我们只需要求用了i条边就可以了 不妨设g(S)(i)表示用了i条边使得点集S连通的概率 设f(S)(i)表示用 ...
- POJ 2778 DNA sequence
QAQ 做完禁忌 又做过文本生成器 这道题就是个水题啦 首先转移方程还是文本生成器的转移方程 但是注意到L很大,但是节点数很小 转移都是固定的,所以我们可以用AC自动机来构造转移矩阵 之后进行矩阵乘法 ...
- 非常好的Demo网站
http://www.xdemo.org/
- *IntelliJ IDEA使用Hibernate连接数据库
在IntelliJ IDEA中配置MySQL Database.
- WCF的通信
[ServiceContract] public interface IContractDemoOne { [OperationContract(IsOneWay=true) ...