Luogu P1074靶形数独【搜索/剪枝】By cellur925
显然是一个搜索。但是开始没有任何的剪枝,暴力从\((1,1)\)点开始搜索,很自然地T了6个点。
#include<cstdio>
#include<algorithm>
using namespace std;
const int group[10][10]=
{
0,0,0,0,0,0,0,0,0,0,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
};
const int sco[10][10]=
{
0,0,0,0,0,0,0,0,0,0,
0,6,6,6,6,6,6,6,6,6,
0,6,7,7,7,7,7,7,7,6,
0,6,7,8,8,8,8,8,7,6,
0,6,7,8,9,9,9,8,7,6,
0,6,7,8,9,10,9,8,7,6,
0,6,7,8,9,9,9,8,7,6,
0,6,7,8,8,8,8,8,7,6,
0,6,7,7,7,7,7,7,7,6,
0,6,6,6,6,6,6,6,6,6,
};
int ans,num[50][50];
bool gong[50][50],hang[50][50],lie[50][50];
void review()
{
int val=0;
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
val+=sco[i][j]*num[i][j];
// printf("%d\n",val);
ans=max(ans,val);
}
bool check(int x,int y,int w)
{
if(gong[group[x][y]][w]||hang[x][w]||lie[y][w]) return 0;
return 1;
}
void dfs(int x,int y)
{
if(x==10)
{
review();
return ;
}
int nx=x,ny=y+1;
if(ny==10) nx++,ny=1;
if(num[x][y]) dfs(nx,ny);
else
{
for(int i=1;i<=9;i++)
{
if(!check(x,y,i)) continue;
gong[group[x][y]][i]=1;
hang[x][i]=1;
lie[y][i]=1;
num[x][y]=i;
dfs(nx,ny);
gong[group[x][y]][i]=0;
hang[x][i]=0;
lie[y][i]=0;
num[x][y]=0;
}
}
}
int main()
{
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
{
int x=0;
scanf("%d",&x);
if(!x) continue;
num[i][j]=x;
hang[i][x]=1;
lie[j][x]=1;
gong[group[i][j]][x]=1;
}
dfs(1,1);
printf("%d",ans==0 ? -1 : ans);
return 0;
}
考虑剪枝。从人类智慧的角度出发,如果是我们玩数独虽然我好像没怎么玩过,我们一定是从填的多的区域出发,因为有更少的决策可供我们选择。那么在这里我们也可以借鉴这个思路,每次统计一下每行每列的有多少数是已经填了的,得到一个最优的坐标,从它出发进行搜索。这个算法保证了我们每次搜的一定是没有填数的,使复杂度优秀了许多。
#include<cstdio>
#include<algorithm>
using namespace std;
const int group[10][10]=
{
0,0,0,0,0,0,0,0,0,0,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
};
const int sco[10][10]=
{
0,0,0,0,0,0,0,0,0,0,
0,6,6,6,6,6,6,6,6,6,
0,6,7,7,7,7,7,7,7,6,
0,6,7,8,8,8,8,8,7,6,
0,6,7,8,9,9,9,8,7,6,
0,6,7,8,9,10,9,8,7,6,
0,6,7,8,9,9,9,8,7,6,
0,6,7,8,8,8,8,8,7,6,
0,6,7,7,7,7,7,7,7,6,
0,6,6,6,6,6,6,6,6,6,
};
int cn,ans,num[50][50];
int cnt_hang[50],cnt_lie[50];
bool gong[50][50],hang[50][50],lie[50][50];
void review()
{
int val=0;
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
val+=sco[i][j]*num[i][j];
// printf("%d\n",val);
ans=max(ans,val);
}
bool check(int x,int y,int w)
{
if(gong[group[x][y]][w]||hang[x][w]||lie[y][w]) return 0;
return 1;
}
void dfs(int x,int y,int cnt)
{
if(cnt==81)
{
review();
return ;
}
for(int i=1;i<=9;i++)
{
if(!check(x,y,i)) continue;
gong[group[x][y]][i]=1;
hang[x][i]=1;
lie[y][i]=1;
num[x][y]=i;
cnt_hang[x]++;cnt_lie[y]++;
int qwq=-1,qaq=-1,bx=0,by=0;
for(int j=1;j<=9;j++)
if(cnt_hang[j]>qwq&&cnt_hang[j]<9)
qwq=cnt_hang[j],bx=j;
for(int j=1;j<=9;j++)
if(cnt_lie[j]>qaq&&(!num[bx][j]))
qaq=cnt_lie[j],by=j;
dfs(bx,by,cnt+1);
gong[group[x][y]][i]=0;
hang[x][i]=0;
lie[y][i]=0;
num[x][y]=0;
cnt_hang[x]--;cnt_lie[y]--;
}
}
int main()
{
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
{
int x=0;
scanf("%d",&x);
if(!x) continue;
num[i][j]=x;
cnt_hang[i]++;
cnt_lie[j]++;
hang[i][x]=1;
lie[j][x]=1;
gong[group[i][j]][x]=1;
cn++;
}
int qwq=-1,qaq=-1,bx=0,by=0;
for(int i=1;i<=9;i++)
if(cnt_hang[i]>qwq&&cnt_hang[i]<9)
qwq=cnt_hang[i],bx=i;
for(int i=1;i<=9;i++)
if(cnt_lie[i]>qaq&&(!num[bx][i]))//注意这里找一个没有填数的坐标
qaq=cnt_lie[i],by=i;
dfs(bx,by,cn);
printf("%d",ans==0 ? -1 : ans);
return 0;
}
Warning
开始写自己的暴力写法的时候傻了两次:
①没输入输出(???)果然T的无可救药
②因为我确定宫和价值都是用数组打出表存的,而开始把数组开的很大,\(50*50\),但是我们打出的表的部分不是另起一行,编译后会被理解连续的一段,于是我们要限制数组大小,使恰好能够填入数。
Luogu P1074靶形数独【搜索/剪枝】By cellur925的更多相关文章
- 洛谷P1074 靶形数独 [搜索]
题目传送门 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了 ...
- luogu P1074 靶形数独
题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的 ...
- P1074 靶形数独
P1074 靶形数独正着搜80分,完全倒置95分,完全倒置后左右再倒置,就会A掉,到时候脑洞要大一些. #include<iostream> #include<cstdio> ...
- 洛谷——P1074 靶形数独
P1074 靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z ...
- 洛谷 P1074 靶形数独(剪枝)
//人生中第一道蓝题(3.5h) 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请 ...
- P1074 靶形数独题解
题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶 ...
- [洛谷P1074] 靶形数独
洛谷题目链接:靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博 ...
- [NOIP2009] 提高组 洛谷P1074 靶形数独
题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的 ...
- 洛谷—— P1074 靶形数独
https://www.luogu.org/problem/show?pid=1074 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但 ...
随机推荐
- 20170316 ABAP注意点
1.debug 时在MODIFY db from table 后数据便提交了: 一般情况下,更新数据库需要commit,但debug会自动commit,程序结束也会自动commit. 2.使用at n ...
- ThinkPHP Widget模块开发流程
初识ThinkPHP的Widget,现把模块开发的流程发布如下,也方便以后自己查阅: 一.新建数据库表self_modules,sql代码如下 CREATE TABLE `self_modules` ...
- 模拟等待事件:db file sequential read
相关知识: db file sequential read 单块读 optimizer_index_cost_adj 这个初始化参数代表一个百分比,取值范围在1到10000之间.该参数表示索引扫描和 ...
- c语言之秒数算法
// 水仙花树:是指一个3位数字,立方和 等于该数本身 // 秒数算法:随便输入一个大于0的数,求出对应的多少小时多少分钟多少秒 #include <stdio.h> / int main ...
- 【mysql】mysql innodb 配置详解
MySQL innodb 配置详解 innodb_buffer_pool_size:这是InnoDB最重要的设置,对InnoDB性能有决定性的影响.默认的设置只有8M,所以默认的数据库设置下面Inno ...
- CI 模型公用查询函数
/** * 多字段条件查询数据 * @param array $val array("name" => $value).name为要操作的字段,value为要操作的值 * @ ...
- 存储过程系列四: decode函数使用学习
Oracle 中 decode 函数用法 含义解释:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 该函数的含义如下:IF 条件=值1 THEN RETURN(翻译 ...
- linux系统配置之bash shell的配置(centos)
linux系统开机启动过程的最后阶段会由init进程根据启动方案(运行级:0-6)启动许多基本的服务程序,为用户提供各种各样的服务.在启动这些服务的最后会启动一个为用户提供操作环境的服务,用户就是通过 ...
- CodeForces990G:GCD Counting(树分治+GCD)
You are given a tree consisting of nn vertices. A number is written on each vertex; the number on ve ...
- JVM介绍(一)
JVM是运行在操作系统之上的,它与硬件没有直接的交互 类装载器ClassLoader 负责加载class文件,class文件在文件开头有特定的文件标示,并且ClassLoader只负责class文件的 ...