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 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但 ...
随机推荐
- 2018.11.06 生成器函数进阶&列表推导式&生成器表达式
1.生成器函数进阶 2.列表推导式 3.生成器表达式
- VB.Command()的参数
VB.Command()的参数的来源有三个地方 1配置文件2启动参数3框架
- java XML-RPC
1.XML-RPC简介 xml rpc是使用http协议做为传输协议的rpc机制,使用xml文本的方式传输命令和数据.一个rpc系统,必然包括2个部分:1.rpc client,用来向rpc serv ...
- [usaco2008feb_gold]路面修整
FJ打算好好修一下农场中某条凹凸不平的土路.按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中. 整条路被分成了N段,N个整数A_1 ...
- TestNG测试用例编写和执行
编写TestNG用例测试基本上包括以下步骤: 编写业务逻辑 针对业务逻辑中涉及的方法编写测试类,在代码中插入TestNG的注解 直接执行测试类或者添加一个testng.xml文件 运行 TestNG. ...
- linux系统CentOS6.5下tokudb数据库引擎的安装
tokuDB是一个关于mysql数据引擎的开源项目,官网对其特点的描述主要有三点: 1.高压缩比,官方宣称可以达到1:12. 2.高insert性能,官方称至少比innodb高9倍. 3.可以在线添加 ...
- Linux-awk和shell编程初步
1 awk 格式: awk -选项 '处理' 输入 awk -F : '{print $1}' file -F指定分隔符, 默认是空格 $1 分割后的第一部分 $0 获得所有部分 NF 表示以分隔符分 ...
- rsync(四)技术报告
1.1 摘要 本报告介绍了一种将一台机器上的文件更新到和另一台机器上的文件保持一致的算法.我们假定两台机器之间通过低带宽.高延迟的双向链路进行通信.该算法计算出源文件中和目标文件中一致的部分(译者注: ...
- 蓝桥杯 2014本科C++ B组 地宫取宝 DFS+记忆化搜索
历届试题 地宫取宝 时间限制:1.0s 内存限制:256.0MB 问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角 ...
- 2.row_number() over (partition by col1 order by col2)的用法
row_number() over (partition by col1 order by col2) 表示根据COL1分组,在分组内部根据 COL2排序,而此函数计算的值就表示每组内部排序后的顺序编 ...