题意:

题目传送门

可以看做一个人手中有一些宝石,并将宝石分成两组,一组的编号为 1 至 n×m/2,二组为 n×m/2+1 至 n×m+1。当两组两个宝石编号相差为 n×m/2 为一对。现在要遍历一个 n×m 的方阵,只能走上下左右,且每个格子必须且仅能到过 1 次。并在遍历同时对每一个格子放入宝石。即遍历的第 i 个格子放入编号为 i 的宝石。

对于一对宝石,如果第一组的宝石在第 x1 行第 y1 列,第二组宝石的在第 x2 行第 y2 列,则称它们的分值为 k1×abs(x1-x2)+k2×abs(y1-y2)。

现在要找出一种遍历顺序,使分值最大一对宝石分值最小,输出这个最小的最大分值。

思路:

看到是遍历,且数据范围非常小,考虑用 dfs。不过如果不加剪枝优化的爆搜,肯定会 TLE 飞,因此考虑剪枝。

首先是一个很好想的最优化剪枝:如果当前记录的最大值已经比之前的方案大了,那就不可能更新答案,没必要搜索,直接

返回。

但只有这一个剪枝还不行,我们发现题目中一个很重要的事:每个格子必须且仅能到过 1 次。因此当发现已经不可能满足要求的时候,便可以直接返回。

那如何判断呢?

当一个现在这个点的上下走过且左右没走,或者左右走过上下没走,则不能满足要求。

因为当上下走过时,他们所联通的路线一定将左右分别能到达的点分隔成两个连通块,左右走过上下没走也是同理。

画个图方便理解一下:

有了这些就可以愉快的写代码了。

代码:

请勿抄袭。

#include<bits/stdc++.h>
using namespace std;
int n,m,k1,k2;
//与题目中意义一致
int ans=1e10;//记录答案
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1}; //移动的方向数组
bool f[61][61];//记录是否被走过
int q[2500][2];//记录第一组宝石所在的点
inline void dfs(int x,int y,int p,int mmax)
//x,y:当前点的坐标,p:搜到的宝石编号,mmax:目前的最大的分数
{
if(mmax>=ans) return;//最优性剪枝
if(f[x+1][y]&&f[x-1][y]&&!f[x][y+1]&&!f[x][y-1]) return;
if(f[x][y+1]&&f[x][y-1]&&!f[x+1][y]&&!f[x-1][y]) return;
//两种不可能完成遍历的情况
if(p<=n*m/2) q[p][0]=x,q[p][1]=y;//第一组,直接存储
else//第二组,开始计算
{
mmax=max(mmax,(k1*abs(x-q[p-(n*m/2)][0])+k2*abs(y-q[p-(n*m/2)][1])));//根据公式求值
}
if(p==n*m)//搜索完了
{
if(mmax<ans) ans=mmax;//能更新答案则更新
return;
}
for(int i=0;i<4;i++)//继续向能走到的点搜索
{
int xx=x+dx[i];
int yy=y+dy[i];
if(!f[xx][yy])//没走过,可以走
{
f[xx][yy]=1;//标记
dfs(xx,yy,p+1,mmax);
f[xx][yy]=0;//回溯
}
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&k1,&k2);
for(int i=0;i<=n+1;i++) f[i][0]=1,f[i][m+1]=1;
for(int i=0;i<=m+1;i++) f[0][i]=1,f[n+1][i]=1;
//上面两个循环是边界处理,因为不能走出方阵,所以将边界设为1,防止出界
f[1][1]=1;
dfs(1,1,1,0);//从1,1点开始搜索
printf("%d\n",ans);//输出
return 0;
}

写题解不易,点个赞呗。

P1585 魔法阵 题解的更多相关文章

  1. 洛谷 P2119 魔法阵 题解

    Analysis 这道题也是考试题,我也依然打了个n三次方暴力.正解是先枚举差,再枚举c和d,a和b用乘法原理优化,这样就能大大减少时间. #include<iostream> #incl ...

  2. (算是dp吧) 小茗的魔法阵 (fzu 2225)

    http://acm.fzu.edu.cn/problem.php?pid=2225   Problem Description 在打败了易基•普罗布朗.诺姆•普罗布朗之后,小茗同学开始挑战哈德•普罗 ...

  3. FZU 2099 魔法阵(计算几何)

     Problem 2099 魔法阵 Accept: 120    Submit: 289 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Probl ...

  4. NOI2014魔法森林题解报告

    题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,-,n,边标号为 1,2,3,-, ...

  5. BZOJ3669:[NOI2014]魔法森林——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3669 https://www.luogu.org/problemnew/show/P2387 为了得 ...

  6. NOIP2016 T4 魔法阵 暴力枚举+前缀和后缀和优化

    想把最近几年的NOIP T4都先干掉,就大概差16年的,所以来做一做. 然后这题就浪费了我一整天QAQ...果然还是自己太弱了QAQ 点我看题 还是pa洛谷的... 题意:给m个物品,每个物品有一个不 ...

  7. FZU 2225 小茗的魔法阵 扫描线+树状数组

    这个题和一个CF上的找"Z"的题差不多,都是扫描线+树状数组 从右上角的主对角线开始扫描,一直扫到左下角,每次更新,右延伸等于该扫描线的点,注意在其所在的树状数组更新就好了 时间复 ...

  8. [P2119]魔法阵 (模拟?搜索?)

    很玄学 我暴力都没做出来 #include <cstdio> ],vis[],a[],b[],c[],d[]; int main() { //freopen("magic.in& ...

  9. [NOI2014]魔法森林题解

    这道题正解其实是LCT,然而貌似SPFA也可以成功水过,所以根本不知道LCT的我只能说SPFA了. 这道题最大的限制是两种精灵就意味着一条道可能有两个权值,因此我们需要去将其中一个固定,然后再推另一个 ...

  10. 洛谷2387 BZOJ3669魔法森林题解

    题目链接 BZ链接 这道题被很多人用spfa水了过去,表示很... 其实spfa很好卡,这组数据可以卡掉大多数spfa 链接:密码:rjvk 这里讲一下LCT的做法 我们按照a将边排序,然后依次添加 ...

随机推荐

  1. ThreadLocal 类

    更多内容,访问 IT-BLOG ThreadLocal 并不是一个Thread,而是 ThreadLocalVariable(线程局部变量).也许把它命名为 ThreadLocalVar更加合适.线程 ...

  2. css中所有的选择器(包括比较少见的选择器)

    jQuery.CSS常用选择器 符号 描述 示例 说明 紧接无符号 相当于"并且"关系 input.k-textbox{   ...} 选出input并且包含k-textbox类的 ...

  3. NEFU高级程序设计-期末复习习题组

    1. 用链表实现单词序列倒序输出 题目 用链表实现单词序列倒序输出.与以往不同,请考虑采用一种完全的动态分配方式! 为降低难度,"仁慈"的我已经给出了输出和释放的代码,你只要写出创 ...

  4. python---滚动条操作

    """ 1.让元素滚动到可见区域后,再操作.(大部分的网页自己会滚,直接找元素---下一页) drive.find_element("id",&quo ...

  5. 随机分布和随机数生成——R语言

    在人们的生活中,很多场景都需要用到随机数,例如福利彩票,车牌摇号,公共用房分配等.在用数学模型, 包括概率统计模型处理实际应用中的问题时, 我们希望建立的模型能够尽可能地符合实际情况.但是,实际情况是 ...

  6. 逍遥自在学C语言 | 逻辑运算符

    前言 一.人物简介 第一位闪亮登场,有请今后会一直教我们C语言的老师 -- 自在. 第二位上场的是和我们一起学习的小白程序猿 -- 逍遥. 二.构成和表示方式 逻辑运算符是用来比较和操作布尔值的运算符 ...

  7. 全网最详细 二进制 k8s v1.25.x文档

    二进制安装k8s v1.25.0 IPv4/IPv6双栈 Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes(k8s)二进制高可用安装部署,支持IPv4+IPv6双栈 ...

  8. Luogu P2574 XOR的艺术 P3870 [TJOI2009]开关 P2846 [USACO08NOV]光开关Light Switching SP7259 LITE - Light Switching

    四倍经验题 简单线段树qwq(那你怎么还调了好几个小时) 修改:\(ans[cur]=(r-l+1-ans[cur]);\) 点表示的区间有多长就是有多少盏灯 亮着的关掉 暗的开启 就是上述语句了. ...

  9. 【Vue2.x源码系列06】计算属性computed原理

    上一章 Vue2异步更新和nextTick原理,我们介绍了 JavaScript 执行机制是什么?nextTick源码是如何实现的?以及Vue是如何异步更新渲染的? 本章目标 计算属性是如何实现的? ...

  10. Qt第三方库QtAV--- ubuntu编译与运行

    Qt第三方库QtAV--- ubuntu编译与运行 今天又要接触这个,把一些错误或者不足的地方重新补充下!!!由于前面一段时间,项目中需要借助QtAV接口进行视频播放,特此记录下整个配置过程.整个代码 ...