Problem Statement

     Manao is playing a new game called Reflections. The goal of the game is transferring an artifact in 3-dimensional space from point (0, 0, 0) to point (X, Y, Z). There are two types of moves in the game:

1) The player can move the artifact by 1 unit in the direction of any coordinate axis. So, using this type of move, from point (a, b, c) the artifact can be moved to points (a + 1, b, c), (a - 1, b, c), (a, b + 1, c), (a, b - 1, c), (a, b, c + 1) or (a, b, c - 1).

2) The player can reflect the artifact against any one of the given planes. The reflection works as follows: the artifact disappears at its position before the reflection and appears on the other side of the plane at such a place that the line connecting the old and new positions is perpendicular to the plane and the old and new positions are equidistant from the plane. Reflection against each particular plane can be performed at most once during the game.

The planes are given as vector <int>s mirrorXmirrorY and mirrorZmirrorX[i] corresponds to a plane perpendicular to the X axis with coordinate X = mirrorX[i]mirrorY and mirrorZcontain planes perpendicular to the Y and Z axis in the same fashion. The target position is given in vector <int> finalPositionfinalPosition contains 3 elements, wherefinalPosition[0] is X, finalPosition[1] is Y and finalPosition[2] is Z.

Return the minimum possible number of moves which Manao will need to transfer the artifact.

Definition

    
Class: Reflections
Method: minimumMoves
Parameters: vector <int>, vector <int>, vector <int>, vector <int>
Returns: long long
Method signature: long long minimumMoves(vector <int> mirrorX, vector <int> mirrorY, vector <int> mirrorZ, vector <int> finalPosition)
(be sure your method is public)

Limits

    
Time limit (s): 2.000
Memory limit (MB): 64

Constraints

- finalPosition will contain exactly 3 elements.
- Each element of finalPosition will be between -1,000,000,000 and 1,000,000,000, inclusive.
- mirrorX will contain between 0 and 20 elements, inclusive.
- Each element of mirrorX will be between -1,000,000,000 and 1,000,000,000, inclusive.
- All elements of mirrorX will be distinct.
- mirrorY will contain between 0 and 20 elements, inclusive.
- Each element of mirrorY will be between -1,000,000,000 and 1,000,000,000, inclusive.
- All elements of mirrorY will be distinct.
- mirrorZ will contain between 0 and 20 elements, inclusive.
- Each element of mirrorZ will be between -1,000,000,000 and 1,000,000,000, inclusive.
- All elements of mirrorZ will be distinct.

Examples

0)  
    
{2}
{}
{}
{3, 0, 1}
Returns: 3
Manao can reflect the artifact against the only given plane, making it appear at (4, 0, 0). Afterwards, he can transfer it into the target position by two moves of the first type.
1)  
    
{-5, 1, 4, 2, 3, 6, -6}
{}
{}
{9, 0, 0}
Returns: 2
A possible solution will be moving the artifact to (-1, 0, 0) and then reflecting it against the plane represented by mirrorX[2].
2)  
    
{5, 8}
{}
{}
{4, 0, 0}
Returns: 4
If a reflection against a particular plane was allowed more than once, Manao could transfer the artifact in only three moves.
3)  
    
{5}
{5}
{1, 2, 3}
{10, 12, -1}
Returns: 5
The planes perpendicular to the Z axis are of no use. After performing the reflections against the other two planes, Manao gets the artifact to point (10, 10, 0). Three more moves of the first type are required then.
4)  
    
{8, -3, 21}
{4, 5}
{-7, -2, -1, 7, 14}
{40, -4, 31}
Returns: 10
 

题意大致是:在三维空间中,从原点走到(x,y,z),每次可以向六个方向中的一个方向走一步,或者沿一面镜子对称,问至少行动多少次可以到达终点。

每面镜子都是垂直于x轴、y轴、z轴中的一条轴的平面,且垂直于一条轴的镜子数最多为20。每面镜子最多被用来对称一次。

题解:

代码来自TopCoder Wiki。

若直接进行移动,则只会改变三维中的一维,做对称也一样,所以三维可以分开讨论。

因为镜像操作只是进行对称,所以直接移动可以放在最后进行。这样,我们只要搜索按哪种顺序选用了哪些镜子,将得到的坐标与终点做差,即为在这个维度直接移动的次数。

直接枚举显然会超时,我们可以考虑优化。

考虑垂直于x轴的镜子的操作:若点坐标为a,镜子坐标为b,则对称后点坐标为2*b-a。

经过一系列对称,最终点坐标展开为(2*b[n]-2*b[n-1]+2*[b-2]-......-2*b[2]+2*b[1]-a)或(2*b[n]-2*b[n-1]+2*[b-2]-......+2*b[2]-2*b[1]+a)。

即某面被选用镜子操作的贡献只与选用顺序序号的奇偶性有关。

可以枚举n面奇数序号的镜子与n面偶数序号的镜子,原坐标贡献为正;或枚举n面奇数序号的镜子与n+1面偶数序号的镜子,原坐标贡献为负。

可是这样枚举依旧会TLE。

我们可以采用折半搜索,就不会TLE了,可是十分不好写。

事实上,我们可以分别枚举奇数序号镜子的集合与偶数序号镜子的集合,而不用考虑重复的情况。对于重复的情况,可以看做是一面镜子用了两次(效果等同于不使用),可以正常处理,但一定不是最优解。

枚举好后,用类似于折半搜索的做法合并即可。

代码:

 class Reflections
{
public:
long long solve(vector<int>& M, int P)
{
int N = M.size();
// Compute the sum of each subset.
vector<long long> V[];
for(int i = ; i < << N; i++)
{
long long sum = ;
for(int j = ; j < N; j++) if(i & << j) sum += M[j] * 2ll;
V[__builtin_popcount(i)].push_back(sum);
}
// For each subset find the subset of the same or one lesser size that puts us closest to our target.
long long ret = abs(P);
for(int i = ; i <= (N + ) / ; i++)
{
sort(V[i].begin(), V[i].end());
for(int j = ; j < V[i].size(); j++)
{
// Find subsets of equal size that put us close to P.
int pos = upper_bound(V[i].begin(), V[i].end(), V[i][j] - P) - V[i].begin();
if(pos < V[i].size()) ret = min(ret, * i + abs(P - V[i][j] + V[i][pos]));
if(pos > ) ret = min(ret, * i + abs(P - V[i][j] + V[i][pos - ])); // Find subsets of one lesser size that put us close to P.
if(!i) continue;
pos = upper_bound(V[i - ].begin(), V[i - ].end(), V[i][j] - P) - V[i - ].begin();
if(pos < V[i - ].size()) ret = min(ret, * i - + abs(P - V[i][j] + V[i - ][pos]));
if(pos > ) ret = min(ret, * i - + abs(P - V[i][j] + V[i - ][pos - ]));
}
}
return ret;
}
long long minimumMoves(vector<int> X, vector<int> Y, vector<int> Z, vector<int> P)
{
return solve(X, P[]) + solve(Y, P[]) + solve(Z, P[]);
}
};

TopCoder[SRM513 DIV 1]:Reflections(1000)的更多相关文章

  1. TopCoder[SRM513 DIV 1]:PerfectMemory(500)

    Problem Statement      You might have played the game called Memoria. In this game, there is a board ...

  2. TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization & Codeforces 839 E

    传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相 ...

  3. TopCoder SRM 558 Div 1 - Problem 1000 SurroundingGame

    传送门:https://284914869.github.io/AEoj/558.html 题目简述  一个人在一个n * m棋盘上玩游戏,想要占领一个格子有两个方法: 在这个格子放一个棋子.  这个 ...

  4. TopCoder SRM 566 Div 1 - Problem 1000 FencingPenguins

    传送门:https://284914869.github.io/AEoj/566.html 题目简述: 平面上有中心在原点,一个点在(r,0)处的正n边形的n个顶点.平面上还有m个企鹅,每个企鹅有一个 ...

  5. TopCoder SRM 561 Div 1 - Problem 1000 Orienteering

    传送门:https://284914869.github.io/AEoj/561.html 题目简述: 题外话: 刚开始看题没看到|C|<=300.以为|C|^2能做,码了好久,但始终解决不了一 ...

  6. TopCoder SRM 582 Div 1 - Problem 1000 SemiPerfectPower

    首先我们可以把答案差分,那么我们只需要求出\(1\)~\(x\)范围内的满足条件的数即可. 题目要求的应该是这个东西的个数: \(l \leq a*b^c \leq r(1 \le a < b) ...

  7. Topcoder SRM584 DIV 2 500

    #include <set> #include <iostream> #include <string> #include <vector> using ...

  8. Topcoder SRM583 DIV 2 250

    #include <string> #include <iostream> using namespace std; class SwappingDigits { public ...

  9. 【补解体报告】topcoder 634 DIV 2

    A:应该是道语文题,注意边界就好: B:开始考虑的太复杂,没能够完全提取题目的思维. 但还是A了!我愚蠢的做法:二分答案加暴力枚举, 枚举的时候是完全模拟的,比如每次取得时候都是从大到小的去取,最后统 ...

随机推荐

  1. 解决 Onenote 默认全角输入的一种解决办法(输入法已经设置为默认半角)

    环境说明:Windows 7 x64 Ultimate SP1, QQ 拼音输入法 6.1(5306),Onenote 2016 x64 问题描述:每次打开Onenote,在输入法已经设置为默认半角的 ...

  2. tomcat访问控制及站点部署

    访问控制: 在访问tomcat服务器状态时,出现403错误. 解决方法: [root@localhost ~]# vim /usr/local/tomcat8/conf/tomcat-users.xm ...

  3. vue $emit 子传父

    我们使用子组件传递值给父组件使用 $emit 代码 <!DOCTYPE html> <html lang="en"> <head> <me ...

  4. leetcood学习笔记-108-将有序数组转换为二叉搜索树

    ---恢复内容开始--- 题目描述: 方法一: class Solution(object): def sortedArrayToBST(self, nums): """ ...

  5. R语言 变量

    R语言变量 变量为我们提供了我们的程序可以操作的命名存储. R语言中的变量可以存储原子向量,原子向量组或许多Robject的组合. 有效的变量名称由字母,数字和点或下划线字符组成. 变量名以字母或不以 ...

  6. bzoj1038题解

    [题意分析] 求一个下凸壳与一段折线的距离. [解题思路] 先把直线按斜率排序,求出下凸壳,然后枚举所有的顶点的x坐标求最短y坐标差,复杂度O(nlog2n). [参考代码] #include < ...

  7. NOIp2018集训test-9-19(am&pm)

    AM 这是一套在长沙考过而且我能记得全部正解的题,然后期望得分300实际得分155. T1 很套路,随便搞(我当年是怎么花大半场时间写T1并且写出现在两倍长的代码的??) //Achen #inclu ...

  8. 源码安装zabbix-oracle

    源码安装zabbix_agent4.0.3   1.源码包下载地址:https://www.zabbix.com/download_sources 2.下载完后上传在任意目录用root用户创建以下脚本 ...

  9. IOS自动化打包介绍

    IOS自动化打包介绍  标签: app打包 , Ios打包 , iphone打包 , iphone自动化打渠道包    分类:无线客户端技术, 贴吧技术 摘要 随着苹果手持设备用户的不断增加,ios应 ...

  10. hdu4352-XHXJ's LIS状压DP+数位DP

    (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 题意:传送门  原题目描述在最下面.  在区间内把整数看成一个阿拉伯数字的集合,此集合中最长严格上升子序列的长度为k的个数. 思路: ...