Maigc Cubes:2017 Works Application笔试
来源:互联网 发布:org.apache.xml jar包 编辑:程序博客网 时间:2024/05/19 08:41
给定一个M*M*M的魔方,和N个小魔方,将每一个小魔方融合到大魔方里(小魔方的大小不确定,但是一定小于大魔方),融合的部位将将加起来再对P取余,要求最后的结果一定是全部为0。求出所有小魔方的位置。
思路如下,这个题目似乎没有找到巧妙的解法,所以采用暴力搜索.但是搜索也是有技巧的,我思考之后发现:这个问题很适合双向BFS搜索加减枝。从最终状态全0出发,我们可以每次减去一个魔方的值然后取余(-1%3 = 2),这样可以从最终的状态逆推。
然后从起始状态开始进行状态拓展,这个没有什么好说的。
状态交集: 因为要使用状态交集,所以我们必须要把状态用Map存起来,为什么是Map呢,因为还需要一个value来保存状态经过的路径(小魔方的位置序列).因为必须要将所有小魔方都放进去,所以搜索的层数是固定的,关键在于正反状态有交集的时时候是第(N/2)层。
剪枝技巧: 假设现在有M个的位置不是0,同时剩下的所有小魔方一共有S个元素,那么M>S的时候就应该被剪掉。这个很好理解。同理反向剪枝是针对与初始状态有多少个不同的位置来计算的,同样的剪枝手段。
Python实现如下:
def check(i,j,bound): return i+j>=bounddef zeros_tuple(M): return tuple((tuple((0,)*M for i in range(M))) for j in range(M))def zeros_list(M): return [[[0]*M for i in range(M)] for j in range(M)]def do(big,small,p,P,flag): i,j,k = p length = len(small) res = [[list(v2) for v2 in v1] for v1 in big ] for l1 in range(length): for l2 in range(length): for l3 in range(length): _i,_j,_k = i+l1,j+l2,k+l3 res[_i][_j][_k] = (res[_i][_j][_k]+flag*small[l1][l2][l3])%P return Tuple(res)def merge(big,small,p,P,pp = False): return do(big,small,p,P,1)def recover(big,small,p,P): return do(big,small,p,P,-1)def Tuple(vec): return tuple(tuple(tuple(v2) for v2 in v1) for v1 in vec)def compute(big,P=0): cnt = 0 for v1 in big: for v2 in v1: for v3 in v2: if v3!=0:cnt+=1 return cntdef compute2(big,big_cube): cnt = 0 for i,v1 in enumerate(big): a = big_cube[i] for j,v2 in enumerate(v1): b = a[j] for k,v3 in enumerate(v2): if v3!=b[k]:cnt+=1 return cntdef bi_bfs(M,N,P,big_cube,s_cubes,count): All_0 = zeros_tuple(M) State1,State2 = {big_cube:[]},{zeros_tuple(M):[]}#initial state c1,c2 = count,count num = 0 for num in range(N): next1,next2 = {},{} small_cube1 = s_cubes[num] small_cube2 = s_cubes[N-num-1] len1 = len(small_cube1) len2 = len(small_cube2) c1 -= len1**3 c2 -= len2**3 for big_cube_tmp1,pos in State1.items(): for i in range(M): if check(i,len1-1,M):break for j in range(M): if check(j,len1-1,M):break for k in range(M): if check(k,len1-1,M):break s = merge(big_cube_tmp1,small_cube1,(i,j,k),P) remain = compute(s,P) if remain>c1: continue next1[s] = pos+[(i,j,k)] #if s in State2:print('zeros2');return next1[s]+State2[s][::-1] if num>=N-2-num and s in State2:print('zeros2');return next1[s]+State2[s][::-1] for big_cube_tmp2,pos in State2.items(): for i in range(M): if check(i,len2-1,M):break for j in range(M): if check(j,len2-1,M):break for k in range(M): if check(k,len2-1,M):break s = recover(big_cube_tmp2,small_cube2,(i,j,k),P) remain = compute2(s,big_cube) if remain > c2: continue next2[s] = pos+[(i,j,k)] if s in next1:print('zeros3');return next1[s]+next2[s][::-1]#return pos path if num>=N-2-num and s in next1:print('zeros3');return next1[s]+next2[s][::-1]#return pos path State1,State2 = next1,next2 print(num,len(State1),len(State2)) print(num,len(State1)*(M-N+1)**3,len(State2)*(M-N+1)**3)def process(): M,N,P = map(int,input().split(' ')) vec = list(map(int,input().split(' '))) big = zeros_list(M) for ind,each in enumerate(vec): _k,_j,_i = ind%M,(ind//M)%M,(ind//(M**2))%M big[_i][_j][_k] = each small_cubes = [] count = 0 for i in range(N): vec = list(map(int,input().split(' '))) n,vec = vec[0],vec[1:] small = zeros_list(n) for ind,each in enumerate(vec): _k,_j,_i = ind%M,(ind//M)%M,(ind//(M**2))%M small[_i][_j][_k] = each count+=n**3 small_cubes.append(small) p = bi_bfs(M,N,P,Tuple(big),small_cubes) for line in p: for i in line: print(i,end = ' ') print()###用来生成测试数据,不是正式代码def Test(): import random M =8 N = 5 P = 10 b = zeros_list(M) pos = [(7,7,7),(3,3,4),(3,3,1),(4,2,1),(3,2,1),(2,6,0),(5,1,1),(4,1,1),(5,6,3),(1,5,2)] num = [1,2,3,4,5,6,7,8,9,2,1] vec = [1,2,1,3,2,1,2,3,2,1,2,2] smalls = [] count=0 for i in range(N): n = vec[i] small = zeros_list(n) for v1 in small: for v2 in v1: for k in range(n): v2[k] = num[i]#random.randint(0,P-1) smalls.append(small) count+=n**3 b = recover(b,small,pos[i],P) #print(b) print() ps = bi_bfs(M,N,P,b,smalls,count) print(ps) for i,small in enumerate(smalls): b = merge(b,small,ps[i],P,True) assert(b == zeros_tuple(M))
C++实现:
#include <iostream>#include <vector>#include <algorithm>#include <unordered_map>#include <functional>using namespace std;struct pos { short i; short j; short k;};class vector_hasher {public: size_t operator()(vector<short> const& vec) const { std::size_t ret = 0; for(size_t i = 0; i!=vec.size(); ++i) { ret ^= std::hash<short>()(vec[i]); } return ret; }};typedef unordered_map<vector<short>, vector<pos>, vector_hasher> State;size_t M, N, P;vector<short> length;vector<short> big_cube;vector<vector<short> > small_cube;vector<short> operate(vector<short>& cube, vector<short>& small_cube, size_t length, pos& position, short flag) { size_t m = position.i; size_t n = position.j; size_t p = position.k; vector<short> new_cube = cube; for (size_t i = 0; i < length; ++i) { for (size_t j = 0; j < length; ++j) { for (size_t k = 0; k < length; ++k) { new_cube[M * M * (i + m) + M * (j + n) + (k + p)] += flag * small_cube[length * length * i + length * j + k]; if (new_cube[M * M * (i + m) + M * (j + n) + (k + p)] < 0) { new_cube[M * M * (i + m) + M * (j + n) + (k + p)] += P; } new_cube[M * M * (i + m) + M * (j + n) + (k + p)] = new_cube[M * M * (i + m) + M * (j + n) + (k + p)] % P; } } } return new_cube;}vector<short> merge(vector<short>& cube, vector<short>& small_cube, size_t length, pos& position) { return operate(cube, small_cube, length, position, 1);}vector<short> split(vector<short>& cube, vector<short>& small_cube, size_t length, pos& position) { return operate(cube, small_cube, length, position, -1);}bool check(size_t i, size_t j) { return i + j > M;}size_t count_zeros(vector<short>& inter) { size_t count = 0; for (size_t i = 0; i < M * M * M; ++i) { if (inter[i] != 0) { ++count; } } return count;}size_t inverse_count(vector<short>& inter) { size_t count = 0; for (size_t i = 0; i < M * M * M; ++i) { if (inter[i] != big_cube[i]) { ++count; } } return count; }vector<pos> bi_bfs(void) { vector<short> all_zeros(M * M * M, 0); State state_1, state_2; state_1.insert(pair<vector<short>, vector<pos> >(big_cube, vector<pos>())); state_2.insert(pair<vector<short>, vector<pos> >(all_zeros, vector<pos>())); size_t count = 0; for (size_t i = 0; i < N; ++i) { count += length[i] * length[i] * length[i]; } size_t c1 = count; size_t c2 = count; for (size_t num = 0; num < N; ++num) { State next_1, next_2; vector<short> small_1 = small_cube[num]; vector<short> small_2 = small_cube[N - num - 1]; size_t length_1 = length[num]; size_t length_2 = length[N - num - 1]; c1 -= length_1 * length_1 * length_1; c2 -= length_2 * length_2 * length_2; for (State::iterator iter = state_1.begin(); iter != state_1.end(); ++iter) { vector<short> cube = iter->first; vector<pos> path = iter->second; for (size_t i = 0; i < M * M * M; ++i) { size_t p = i % M; size_t n = (i / M) % M; size_t m = (i / (M * M)) % M; if (check(m, length_1) || check(n, length_1) || check(p, length_1)) { continue; } pos position; position.i = m; position.j = n; position.k = p; vector<short> new_cube = merge(cube, small_1, length_1, position); size_t remain = count_zeros(new_cube); if (remain > c1) { continue; } path.push_back(position); next_1.insert(pair<vector<short>, vector<pos> >(new_cube, path)); if (num >= N - num - 1 && state_2.find(new_cube) != state_2.end()) { vector<pos> inverse_path = state_2[new_cube]; vector<pos> tmp = next_1[new_cube]; tmp.insert(tmp.end(), inverse_path.rbegin(), inverse_path.rend()); return tmp; } } } for (State::iterator iter = state_2.begin(); iter != state_2.end(); ++iter) { vector<short> cube = iter->first; vector<pos> path = iter->second; for (size_t i = 0; i < M * M * M; ++i) { size_t p = i % M; size_t n = (i / M) % M; size_t m = (i / (M * M)) % M; if (check(m, length_2) || check(n, length_2) || check(p, length_2)) { continue; } pos position; position.i = m; position.j = n; position.k = p; vector<short> new_cube = split(cube, small_2, length_2, position); size_t remain = inverse_count(new_cube); if (remain > c2) { continue; } path.push_back(position); next_2.insert(pair<vector<short>, vector<pos> >(new_cube, path)); if (num >= N - num - 1 && next_1.find(new_cube) != next_1.end()) { vector<pos> inverse_path = next_2[new_cube]; vector<pos> tmp = next_1[new_cube]; tmp.insert(tmp.end(), inverse_path.rbegin(), inverse_path.rend()); return tmp; } } } state_1 = next_1; state_2 = next_2; }}int main() { cin >> M >> N >> P; big_cube.resize(M * M * M); small_cube.resize(N); length.resize(N); vector<pos> position; for (size_t i = 0; i < M * M * M; ++i) { cin >> big_cube[i]; } for (size_t i = 0; i < N; ++i) { cin >> length[i]; size_t l = length[i]; small_cube[i].resize(l * l * l); for (size_t j = 0; j < l * l * l; ++j) { cin >> small_cube[i][j]; } } position = bi_bfs(); for (size_t i = 0; i < position.size(); ++i) { pos p = position[i]; cout << p.i << " " << p.j << " " << p.k << endl; } return 0;}
0 0
- Maigc Cubes:2017 Works Application笔试
- Works Application 2017 笔试题
- Works Application 2017 笔试 [Exam2] Wireless Routers
- Works Application 2017 笔试题 [Exam1] Magic Cube
- Works Application面试总结
- Works Application面试经验
- Works System的笔试
- Works Applications 面试笔试!
- Works Applications的笔试题
- How Tomcat works 之The Application 应用
- Exam 1 Character Recognition - Works Application 16
- 2017 ICPCECIC Make cubes
- Works applications 2014笔试题(1)
- Works applications 笔试题(2)
- Works applications 笔试题(3)
- works
- How the Application Server's Web Container Works
- Exam 2 Maximum Xor with Prefix and Suffix - Works Application 16
- 设计模式之单实例
- 初入nodejs需要注意的问题---fs模块
- C# 反射获取项目下要运行的类
- CSS 基础(025_表单)
- IOS图层Layer学习笔记(三)—— CALayer(下)
- Maigc Cubes:2017 Works Application笔试
- Caffe训练过程:test_iter test_interval等概念
- 使用Xcode8上传成功后,商店里构建版本却没有应用
- IOS图层Layer学习笔记(四)—— CAShapeLayer
- iOS开发遍历集合(NSArray,NSDictionary、NSSet)方法总结
- React Native控件之Text组件介绍
- 网易云课堂:用视频云技术承载3300万用户的流畅学习体验
- 优化UI方面
- 树莓派3的Ubuntu系统的无线网设置