Knight
题目描述:
有一张无限大的棋盘,你要将马从\((0,0)\)移到\((n,m)\)。
每一步中,如果马在\((x,y)(x,y)\),你可以将它移动到 \((x+1,y+2)(x+1,y+2)\),
\((x+1,y-2)(x+1,y−2)\),\((x-1,y+2)(x−1,y+2)\),\((x-1,y-2)(x−1,y−2)\),
\((x+2,y+1)(x+2,y+1)\),\((x+2,y-1(x+2,y−1)\),\((x-2,y+1)(x−2,y+1)或(x-2,y-1)(x−2,y−1)\)。
你需要最小化移动步数。
输入:
第一行一个整数tt表示数据组数 \((1\leq t\leq 1000)\)。

每组数据一行两个整数\(n,m (|n|,|m| \leq 10^9)\)。

输出:
每组数据输出一行一个整数表示最小步数。
样例输入
2
0 4
4 2
样例输出
2
2

  • 由于数据有\(10^9\),所以BFS被毙了(~ ̄▽ ̄)~,没想到什么好的做法,所以BFS打表找规律= ̄ω ̄=。

  • 打表结果及代码

#include<iostream>
#include <queue>
using namespace std;
int dir[8][2] = {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}
};
int n, m;
int maze[1100][1100];
bool vis[1100][1100];
struct Point {int x, y, step;Point(int _x, int _y, int _step) :x(_x), y(_y), step(_step) {}
};
void bfs(int sx, int sy)
{queue<Point>q;q.push(Point(sx, sy, 0));vis[sx][sy] = 1;maze[sx][sy] = 0;while (!q.empty()){int x = q.front().x;int y = q.front().y;int step = q.front().step;maze[x][y] = step;q.pop();for (int i = 0; i < 8; i++){int tx = x + dir[i][0];int ty = y + dir[i][1];if (!vis[tx][ty]&&tx<61&&ty<61&&tx>=0&&ty>=0){q.push(Point(tx, ty, step + 1));vis[tx][ty] = 1;}}}
}
int main() {//freopen("1.txt", "w", stdout);bfs(30, 30);for (int i = 0; i < 60; i++) {for (int j = 0; j <60; j++) {cout << maze[i][j] << " ";}cout << endl;}return 0;
}
  • 从上面看,很明显是有规律的,据说大佬能一眼就看出来,以前我是不信的,直到现场有dalao花了4分钟拿了一血……<@_@>蒟蒻只能慢慢推了。首先先把上面的数据放到Excel里面,先预处理一下,将每个答案作为点,以起点为原点建立平面直角坐标系,结果如下:

之前我犯了一个错误,BFS起点放到数组边界上去了,应该放到偏中心的位置,把表打出来。将答案统一起来看,从2开始,所有相同的答案围成了一个八边形,这个八边形与坐标轴平行的边都是4层,不平行的都是3层,同时答案基本是向外递增的这样看的时候会发现两个特殊的地方,一个是\((0,1),(1,0),(-1,0),(0,-1)\)这四个点为3,\((2,0),(0,2),(0,-2),(-2,0)\)着四个点4,所以将这些点加入特判。
不难看出,这个表关于坐标轴对称(图中蓝色线),同时也关于\(y=+-x\)对称(图中橙色线),所以\(x\)轴正半轴为起点,逆时针划分为8个区域,每个区域都一样,只需要考虑1号区域就行了。
现在考虑的为1号区域,希望找到递增的答案之间存在的关系,这个关系为\(y=x/2\),可以发现这条直线上的整点正好是答案的递增:\(0,0)->(2,1)->(4,2).....->(x,floor(x/2))\)。将这条直线画出来。(floor()是对一个数值向下取整)
现在看\(y=x/2\)下方的点,满足关系\(y<x/2\),也就是\(y<x-y\)(精度问题,计算时应该用double),而且下方的点都是在刚才所说的八边形的4层边上,所以可以发现将这些点作如下变换后可以将横坐标和\(y=x/2\)对应:

double(x-y-y)/4.0*2;

最后将上面这个值取反\(+x-y\)就是答案。同理可以推出\(y=x/2\)上方的点,满足关系\(y>x/2\),在刚才所说的八边形的3层边上,最后推出

double(x-y-y)/3.0*2;
  • Code
#include <cstdio>
#include <cstring>
#include <cmath>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
ll fun(ll x, ll y) {if (x == 1 && y == 0) {return 3;}if (x == 2 && y == 2) {return 4;}ll delta = x - y;if (y>delta) {return delta - 2 * floor(((double)(delta-y)) / 3.0);}else {return delta - 2 * floor(((double)(delta-y)) / 4.0);}
}int main()
{int t;cin >> t;while (t--){ll x, y;cin >> x >> y;x = abs(x);y = abs(y);if (x < y) {swap(x, y);}cout << fun(x, y) << endl;}return 0;
}
  • 最后,为正经题解
    Knight:
    不妨假设\(x>=y>=0\)。
    当\(x<=2y\) 时,定义每一步的冗余值\(w_i=3-dx-dy\),那么\(Σw_i=Σ(2-dx)=3*步数-x-y\),显然我们只需要最小化冗余值。我们先只用(+2,+1)(若x 为奇数则加一步(+1,+2))走到(x,y’),然后通过将(+2,+1)替换为2 个(+1,+2)使得\(0<=y-y’<3\)。
    若\(y-y’=0\),则冗余值为0,显然最小。
    若\(y-y’=1\),则将(+1,+2)替换为(+2,+1)和(-1,+2)或将2 个(+2,+1)替换为(+1,+2),(+1,+2),(+2,-1),冗余值为2,显然最小。(此处需要特判(2,2))
    若\(y-y’=2\),则加上\((+2,+1)和(-2,+1)\),冗余值为4,由于不存在冗余值为1的步,所以最小。
    当\(x>2y\) 时,定义每一步的冗余值\(w_i=2-dx\),那么\(Σw_i=Σ(2-dx)=2*步数-x\),显然我们只需要最小化冗余值。我们先只使用(+2,+1)走到(2y,y),然后用
    (+2,+1)和(+2,-1)走到\((x’,y)使得0<=x-x’<4\)。
    若\(x-x’=0\)则冗余值为0,显然最小。
    若\(x-x’=1\) 则将之前的(+2,+1)改为(+1,+2)和(+2,-1),冗余值为1,显然最
    小。(此处需要特判(1,0))若\(x-x’=2\) 则加上(+1,+2)和(+1,-2),冗余值为2,由x/2+y 的奇偶性可知
    最小。
    若\(x-x’=3\) 则加上(+2,+1),(+2,+1),(-1,-2),冗余值为3,由x/2+y 的奇偶性可知最小。
    时间复杂度O(t)

转载于:https://www.cnblogs.com/FlyerBird/p/9431685.html

2018 Wannafly summer camp Day3--Knight相关推荐

  1. 2020 CCPC Wannafly Winter Camp Day3 部分题解(ACEFG)

    查看题目 A 黑色气球 题意: n个气球,每个气球高度为正整数.给你每两个气球之间的高度和,还原出所有气球的高度,保证答案唯一. 解题思路: 签到题,因为高度的范围不大,直接枚举第一个气球的高度,检测 ...

  2. 阔力梯的树(2020 CCPC Wannafly Winter Camp Day2 Div.12 )dsu on tree

    题解: dsu on tree dsu on tree的基本步骤就不说了 看到这题询问结点的子树问题,而且询问时离线的,首先想到的dsu on tree的这个trick. 本题的难题就是如何维护结点所 ...

  3. Wannafly summer camp

    2053: Birthday 样例输入 3 3 1 2 1 2 1 2 样例输出 5 分析: 考虑费用流时把每个part拆成n个点,选择第i个点的代表为放置i块蛋糕和(i - 1)块蛋糕的时间差,这个 ...

  4. 2019 wannafly winter camp day5-8代码库

    目录 day5 5H div2 Nested Tree (树形dp) 5F div2 Kropki (状压dp) 5J div1 Special Judge (计算几何) 5I div1 Sortin ...

  5. CCPC-Wannafly Winter Camp Day3 (Div2, onsite) I 石头剪刀布(按秩合并并查集)

    题解:每次有两个事件: y y去挑战xx,如果赢了可以坐在x x的位置,打平或者输了就要被淘汰. 询问在进行所有一类事件后,有多少种情况可以让x x现在还没有被淘汰. 对于第二类事件,我们假设x x挑 ...

  6. Wannafly Winter Camp Day 3 G排列(贪心)

    思路来源 jls%%% 题解 赛后补队友AC的水题可还行 最先出现的单减子序列对应的位置,一定是那些最小值的位置 先把那些放满,剩下的贪心选使字典序最小,就把剩下的从前到后扫一遍从小到大放 代码 #i ...

  7. wannafly summer camp day6

    H--卡牌游戏:https://www.nowcoder.com/acm/contest/202/H 题意:卡牌的数量为无限,种类为 N ,其中 M 种稀有卡牌,问期望抽多少次能抽到 K 张稀有卡牌( ...

  8. CCPC-Wannafly Winter Camp Day3 (Div2, onsite) F 小清新数论 欧拉函数的利用 莫比乌斯反演 杜教筛

    F - 小清新数论 做法一:欧拉函数 #include<stdio.h> #include<bits/stdc++.h> using namespace std; #defin ...

  9. 2020 CCPC Wannafly Winter Camp Day2 Div.12——A 托米的字符串【构造、数学】

    题目传送门 题目描述 托米有一个字符串,他经常拿出来玩.这天在英语课上,他学习了元音字母 a , e , i , o , u {a,e,i,o,u} a,e,i,o,u 以及半元音 y {y} y . ...

最新文章

  1. 远程挂载 NFS 共享目录引发死机问题
  2. [云炬mysql数据库笔记] Work2
  3. ubuntu16 redis5.0以后版本集群部署示例
  4. 2018/8/9 MultiU 6 并查集+dfs,反向建边提高查询效率 !!! / 最大字段和n维(降维)/ 状压+中途相遇法...
  5. 当全家人一起看电影,播到羞羞镜头时......
  6. [Java基础]线程基础与实现多线程
  7. uml+oopc嵌入式c语言开发精讲_嵌入式开发中更接近底层的汇编与C语言
  8. 阿里云提示微擎被挂图片木马详解
  9. error : flash system error_求求你,别再用 System.out.println 了!
  10. Vue学习笔记(四)—— 前端路由
  11. rs232无线串口服务器,低成本WIFI串口服务器
  12. 如何优化内存?Unity中的内存种类;冯乐乐的总结的优化技术。
  13. 精心收集17套电子课件
  14. 星球日报 | Huobi Prime 首期项目 TOP “中签率”2%,开盘暴涨 27 倍
  15. OSPF多实例路由防环检测功能介绍
  16. 短视频制作小技巧,配音字幕都要跟上,做好细节才能成功
  17. MUI极简的JS函数
  18. 【机器学习】Radius Neighbors Classifier(rNN,radius nearest neighbors)
  19. 物联网安全研究之二:IoT系统攻击面定义分析
  20. 用hadoop计算PI值

热门文章

  1. 【CyberSecurityLearning 62】文件包含
  2. 搭建XSS (跨网站指令码) 测试平台
  3. 调用max函数求两个数中较大值
  4. 关于解决tomcat的一个错误
  5. C 语言资源大全中文版
  6. PyTorch基础(八)----- torch.split()方法
  7. linux下启动和关闭网卡命令
  8. zcmu1710(dp)
  9. hdu6375(2018 “百度之星”程序设计大赛 - 初赛(A))
  10. Java关于equals()方法和“==”逻辑运算符的区别简介