TopCoder[SRM513 DIV 1]:Reflections(1000)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
题意大致是:在三维空间中,从原点走到(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)的更多相关文章
- TopCoder[SRM513 DIV 1]:PerfectMemory(500)
Problem Statement You might have played the game called Memoria. In this game, there is a board ...
- TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization & Codeforces 839 E
传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相 ...
- TopCoder SRM 558 Div 1 - Problem 1000 SurroundingGame
传送门:https://284914869.github.io/AEoj/558.html 题目简述 一个人在一个n * m棋盘上玩游戏,想要占领一个格子有两个方法: 在这个格子放一个棋子. 这个 ...
- TopCoder SRM 566 Div 1 - Problem 1000 FencingPenguins
传送门:https://284914869.github.io/AEoj/566.html 题目简述: 平面上有中心在原点,一个点在(r,0)处的正n边形的n个顶点.平面上还有m个企鹅,每个企鹅有一个 ...
- TopCoder SRM 561 Div 1 - Problem 1000 Orienteering
传送门:https://284914869.github.io/AEoj/561.html 题目简述: 题外话: 刚开始看题没看到|C|<=300.以为|C|^2能做,码了好久,但始终解决不了一 ...
- TopCoder SRM 582 Div 1 - Problem 1000 SemiPerfectPower
首先我们可以把答案差分,那么我们只需要求出\(1\)~\(x\)范围内的满足条件的数即可. 题目要求的应该是这个东西的个数: \(l \leq a*b^c \leq r(1 \le a < b) ...
- Topcoder SRM584 DIV 2 500
#include <set> #include <iostream> #include <string> #include <vector> using ...
- Topcoder SRM583 DIV 2 250
#include <string> #include <iostream> using namespace std; class SwappingDigits { public ...
- 【补解体报告】topcoder 634 DIV 2
A:应该是道语文题,注意边界就好: B:开始考虑的太复杂,没能够完全提取题目的思维. 但还是A了!我愚蠢的做法:二分答案加暴力枚举, 枚举的时候是完全模拟的,比如每次取得时候都是从大到小的去取,最后统 ...
随机推荐
- 解决 Onenote 默认全角输入的一种解决办法(输入法已经设置为默认半角)
环境说明:Windows 7 x64 Ultimate SP1, QQ 拼音输入法 6.1(5306),Onenote 2016 x64 问题描述:每次打开Onenote,在输入法已经设置为默认半角的 ...
- tomcat访问控制及站点部署
访问控制: 在访问tomcat服务器状态时,出现403错误. 解决方法: [root@localhost ~]# vim /usr/local/tomcat8/conf/tomcat-users.xm ...
- vue $emit 子传父
我们使用子组件传递值给父组件使用 $emit 代码 <!DOCTYPE html> <html lang="en"> <head> <me ...
- leetcood学习笔记-108-将有序数组转换为二叉搜索树
---恢复内容开始--- 题目描述: 方法一: class Solution(object): def sortedArrayToBST(self, nums): """ ...
- R语言 变量
R语言变量 变量为我们提供了我们的程序可以操作的命名存储. R语言中的变量可以存储原子向量,原子向量组或许多Robject的组合. 有效的变量名称由字母,数字和点或下划线字符组成. 变量名以字母或不以 ...
- bzoj1038题解
[题意分析] 求一个下凸壳与一段折线的距离. [解题思路] 先把直线按斜率排序,求出下凸壳,然后枚举所有的顶点的x坐标求最短y坐标差,复杂度O(nlog2n). [参考代码] #include < ...
- NOIp2018集训test-9-19(am&pm)
AM 这是一套在长沙考过而且我能记得全部正解的题,然后期望得分300实际得分155. T1 很套路,随便搞(我当年是怎么花大半场时间写T1并且写出现在两倍长的代码的??) //Achen #inclu ...
- 源码安装zabbix-oracle
源码安装zabbix_agent4.0.3 1.源码包下载地址:https://www.zabbix.com/download_sources 2.下载完后上传在任意目录用root用户创建以下脚本 ...
- IOS自动化打包介绍
IOS自动化打包介绍 标签: app打包 , Ios打包 , iphone打包 , iphone自动化打渠道包 分类:无线客户端技术, 贴吧技术 摘要 随着苹果手持设备用户的不断增加,ios应 ...
- hdu4352-XHXJ's LIS状压DP+数位DP
(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 题意:传送门 原题目描述在最下面. 在区间内把整数看成一个阿拉伯数字的集合,此集合中最长严格上升子序列的长度为k的个数. 思路: ...