洛谷 P1549 [NOIP1997 提高组] 棋盘问题

Problem

构造一个\(n\times n(n\le 10)\)的矩阵,在矩阵中填入\(1,2,\dots,n^2\),使得任意相邻的数之和为素数。

约定:左上角的格子里必须填数字\(1\)。

不存在解则输出NO,存在的话输出所有解中,第一行和第一列之和最小的排列方案。

Solution

首先\(n\le10\),可以暴搜。

剪枝1

预处理出200以内所有的质数。

剪枝2

为了保证第一行和第一列之和最小,我们可以先填第一行和第一列,再填行列均在\([2,n]\)中的格子并优先选择大的数填放。那么我们得到的第一个合法的方案后,可以记录此时的第一行和第一列的和并对之后填第一行第一列的和进行最优化剪枝

这样就有60pts了。

剪枝3

预处理出\(i+j\)是不是质数。

大概就是一点常数优化,但是这让check函数比较好写。

剪枝4

每填入一个格子,就将其与其四周的已经填了的格子进行判断其和是否为质数。而不是等到构造完毕了再整体判断。

这样进行下一步判断时,前面的方案一定是合法的。并且最后也不需要再进行判断了。

剪枝5

假设当前的第一行+第一列为sum。

如果以当前的第一行第一列搜索到了一组正解,那么即使更新最小的第一行+第一列,并直接退出对右下角的格子的搜索。因为即使又搜出来的几组解,这些解的sum和当前最优解的sum没有区别。

这个时候应该及时的去调整第一行和第一列

到这里,您就已经可以A了这道题了。

如果您对于您的剪枝十分自信,不妨去看一看加强版:P5512

Code

/**************************************************************
* Problem: 1549
* Author: Vanilla_chan
* Date: 20210315
**************************************************************/
//预编译等部分已去除
#define M 210
#define N 20
int n;
bool book[M];
int prime[M][M];
void init()
{
book[1]=1;
for(int i=2;i<=200;i++)
{
if(!book[i])
{
for(int j=2;i*j<=200;j++)
{
book[i*j]=1;
}
}
}
for(int i=1;i<=n*n;i++)
for(int j=1;j<=n*n;j++)
prime[i][j]=book[i+j];
}
int ans;
int ANS[N][N];
int now[N][N];
bool vis[M];
int dt[4][2]={0,1,0,-1,1,0,-1,0};
IL bool exist(int x)
{
return x>=1&&x<=n;
}
bool check(int x,int y)
{
for(int t=0;t<4;t++)
{
if(exist(x+dt[t][0])&&exist(y+dt[t][1]))
{
if(now[x+dt[t][0]][y+dt[t][1]]!=0)
{
if(prime[now[x][y]][now[x+dt[t][0]][y+dt[t][1]]])
{
return 0;
}
}
}
}
return 1;
}
void dfs3(int x,int y,int sum)
{
if(sum>=ans) return;
if(y==n+1) y=2,x++;
if(x==n+1)
{
ans=sum;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
ANS[i][j]=now[i][j];
}
}
return;
}
for(int i=n*n;i>=1;i--)
{
if(vis[i]) continue;
vis[i]=1;
now[x][y]=i;
if(check(x,y)) dfs3(x,y+1,sum);
vis[i]=0;
now[x][y]=0;
}
}
void dfs2(int y,int sum)
{
if(sum>=ans) return;
if(y==n+1)
{
dfs3(2,2,sum);
return;
}
for(int i=1;i<=n*n;i++)
{
if(vis[i]) continue;
vis[i]=1;
now[1][y]=i;
if(check(1,y)) dfs2(y+1,sum+i);
now[1][y]=0;
vis[i]=0;
}
}
void dfs1(int x,int sum)
{
if(sum>=ans) return;
if(x==n+1)
{
dfs2(2,sum);
return;
}
for(int i=1;i<=n*n;i++)
{
if(vis[i]) continue;
vis[i]=1;
now[x][1]=i;
if(check(x,1)) dfs1(x+1,sum+i);
vis[i]=0;
now[x][1]=0;
}
}
int main()
{
n=read();
init();
now[1][1]=1;
vis[1]=1;
ans=100000;
dfs1(2,0);
if(ans==100000) cout<<"NO"<<endl;
else
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout<<ANS[i][j]<<" ";
}
cout<<endl;
}
}
return 0;
}

洛谷 P1549 [NOIP1997 提高组] 棋盘问题的更多相关文章

  1. 洛谷P1312 [NOIP2011提高组Day1T3]Mayan游戏

    Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游 ...

  2. 洛谷 P2678 & [NOIP2015提高组] 跳石头

    题目链接 https://www.luogu.org/problemnew/show/P2678 题目背景 一年一度的“跳石头”比赛又要开始了! 题目描述 这项比赛将在一条笔直的河道中进行,河道中分布 ...

  3. 洛谷 P1025 & [NOIP2001提高组] 数的划分(搜索剪枝)

    题目链接 https://www.luogu.org/problemnew/show/P1025 解题思路 一道简单的dfs题,但是需要剪枝,否则会TLE. 我们用dfs(a,u,num)来表示上一个 ...

  4. 洛谷P1514 [NOIP2010提高组T4]引水入城

    P1514 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城 ...

  5. 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制

    P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...

  6. 洛谷P1083 [NOIP2012提高组Day2T2]借教室

    P1083 借教室 题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借 ...

  7. 洛谷P1315 [NOIP2011提高组Day2T3] 观光公交

    P1315 观光公交 题目描述 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第 0 分钟出现在 1号 ...

  8. 洛谷P1313 [NOIP2011提高组Day2T1]计算系数

    P1313 计算系数 题目描述 给定一个多项式(by+ax)^k,请求出多项式展开后x^n*y^m 项的系数. 输入输出格式 输入格式: 输入文件名为factor.in. 共一行,包含5 个整数,分别 ...

  9. 洛谷P1003 [NOIP2011提高组Day1T1]铺地毯

    P1003 铺地毯 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号 ...

  10. 洛谷P1006 NOIP提高组2008 传纸条

    P1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无 ...

随机推荐

  1. 市场教父 André Kostolany

    大家好,我是 沃伦·爱德华·巴菲特(Warren Edward Buffett,1930 年 8 月 30 日 - ) 查尔斯·托马斯·芒格(Charles Thomas Munger,1924 年 ...

  2. mongodb logical sessions can't have multiple authenticated users

    前言 使用 mongodb db.auth,切换用户时,报以下错误 logical sessions can't have multiple authenticated users 原因是 mongo ...

  3. Tomcat性能优化以及 jvm 参数设置

    linux ps 命令的结果中 VSZ,RSS,STAT 的含义和大小 参数名 含义 单位 USER 进程所属用户   PID 进程ID   %CPU 进程占用CPU百分比   %MEM 进程占用内存 ...

  4. linux 下给网卡添加ipv6、路由

    route命令的使用举例如下:   route // 显示路由信息.   route add –host 192.168.1.110 dev eth0  // 给网卡eth0的路由表中加入新地址192 ...

  5. DEV插件--Spreadsheet1电子表格

    常用操作Spreadsheet常用属性标题栏是否可见 Spreadsheet1.TitleBar.Visible=true标题栏背景颜色 Spreadsheet1.TitleBar.Interior. ...

  6. 【Python】Flask API 登录

    Flask API 登录 零.起因 最近要写uniapp客户端,服务器使用的是Python的Flask框架,为了实现用户登录,在网上查到了一些Flask的扩展,其中比较简单的就是flask_httpa ...

  7. Quartz.NET - 教程 2: 作业和触发器

    译者注: 目录在这 Quartz.NET 3.x 教程 原文在这 Lesson 2: Jobs And Triggers Quartz API Quartz API 的主要接口和类如下: ISched ...

  8. 轻松的工作(deepseek)

    组长:"这里有一百多个地震波形文件,把每一个地震建立一个文件夹,并把地震波形放到对应日期的地震中." 我想:一个一个整好麻烦想摸会鱼 让我们来deepseek吧~ 首先,生成文件夹 ...

  9. 学习Kotlin语法(三)

    简介 在上一节,我们对Kotlin中面向对象编程(OOP)的相关知识有了大致的了解,本章节我们将去进一步了解函数.lambada表达式.内联函数.操作符重载.作用域函数. 目录 函数 函数的使用 参数 ...

  10. 应急响应 - Linux基础篇

    一.Linux应急响应流程 数据备份:所有涉及到分析以及证据的材料都需要提前进行备份,这样也方便之后还有分析人员或者防止数据被篡改或者覆盖. 备份用户信息文件 cat /etc/passwd > ...