题目传送门

显然是一个搜索。但是开始没有任何的剪枝,暴力从\((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的更多相关文章

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

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

  2. luogu P1074 靶形数独

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

  3. P1074 靶形数独

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

  4. 洛谷——P1074 靶形数独

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

  5. 洛谷 P1074 靶形数独(剪枝)

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

  6. P1074 靶形数独题解

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

  7. [洛谷P1074] 靶形数独

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

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

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

  9. 洛谷—— P1074 靶形数独

    https://www.luogu.org/problem/show?pid=1074 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但 ...

随机推荐

  1. 基于 phantomjs 的自动化测试---(1)

    它主要靠js脚本来模拟操作一般流程是写代码写代码写代码open 某个 url监听 onload 事件事件完成后调用 sendEvent 之类的 api 去点击某个 DOM 元素所在 point触发交互 ...

  2. SQL 关联操作

  3. Tomcat Session Clustering

    搭建 Tomcat 集群需要解决很多的问题,其中之一就是要解决 Session 共享问题.小规模集群可以使用 Tomcat 提供的 Session Clustering 来解决. For the im ...

  4. 官方文档Core Technologies - Part 1

    首先介绍系列文章内容及Spring Framework官方文档情况. 在这一系列学习中,我阅读的主要资源是5.1.2 Reference Doc.,以及论坛大神的讲解blog.另外,Spring官方也 ...

  5. nginx启动不了

    nginx简介 Nginx是一个高性能的HTTP和反向代理服务器. 支持的操作系统众多,windows.linux. MacOS X: 可实现负载均衡: Rewrite功能强大: 电商架构大部分都采用 ...

  6. CodeForces - 450B Jzzhu and Sequences —— 斐波那契数、矩阵快速幂

    题目链接:https://vjudge.net/problem/CodeForces-450B B. Jzzhu and Sequences time limit per test 1 second ...

  7. Gym - 100676D Sudoku 基础题

    题目链接:https://odzkskevi.qnssl.com/1110bec98ca57b5ce6aec79b210d2849?v=1490453767 题解: 方法1:用STL的set,把每个数 ...

  8. MYSQL进阶学习笔记十三:MySQL 内存优化!(视频序号:进阶_31)

    知识点十四:MySQL 内存的优化(31) 一.优化MySQL SERVER 7组后台进程: masterthread:主要负责将脏缓存页刷新到数据文件,执行purge操作,触发检查点,合并插入缓冲区 ...

  9. iOS-个人开发者账号转公司开发者账号(邓白氏码申请教程)

    邓白氏编码申请 个人开发者账号转公司开发者账号,首先要申请邓白氏编码-DUNS,打开https://developer.apple.com/support/进行DUNS申请! 步骤如下: 1.选择Me ...

  10. hdu 1236 排名(排序)

    题意:按成绩排序 思路:排序 #include<iostream> #include<stdio.h> #include<string.h> #include< ...