http://acm.hdu.edu.cn/showproblem.php?pid=4801

1. 题目描述
给定一个2×2×22×2×2的魔方,当某个面上的4个小块颜色均相同时,称这个面为complete。求对这个魔方进行n∈[1,7]n∈[1,7]次旋转(沿某个面顺时针或者逆时针)的过程中,求complete的面总和的最大值。魔方及索引如下图所示:

我一直以为魔方只有8种操作

上图再加上反方向的就是8种

但其实下面的往右转和上面的往左转是一样的。。。

并且还忽略了红线的操作

那其实我们可以这么考虑,以每个面为平面旋转,有逆时针和顺时针两种

六个面,6*2=12种操作,然后,我们考虑相对的两个面

我们发现

从中间切开的这两个面,比如说上下,其实这两个操作是一种操作

因此12/2=6

一共只有6种操作,这个题目最多转7次,那么一共有6^7=279936这么多状态

挺少的所以我们可以直接DFS爆搜

并且一个显然的剪枝是,如果上一次对某一个面逆时针,那么这次对这个面顺时针就没有必要了,这相当于还原

代码常量较多,不好调试,需要对照立体图和展开图写出对应的排列关系

(旋转某个面时,该面上的排列也会放生变化

 1 #include <stdio.h>
2 #include <algorithm>
3
4 using namespace std;
5 int f[6][4]={{0,1,2,3},{4,5,10,11},{6,7,12,13},{8,9,14,15},{16,17,18,19},{20,21,22,23}};
6 int sour[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
7 int left0[]={2,0,3,1,6,7,8,9,23,22,10,11,12,13,14,15,16,17,18,19,20,21,5,4};
8 int right0[]={1,3,0,2,23,22,4,5,6,7,10,11,12,13,14,15,16,17,18,19,20,21,9,8};
9 int left1[]={20,1,22,3,10,4,0,7,8,9,11,5,2,13,14,15,6,17,12,19,16,21,18,23};
10 int right1[]={6,1,12,3,5,11,16,7,8,9,4,10,18,13,14,15,20,17,22,19,0,21,2,23};
11 int left2[]={0,1,8,14,4,3,7,13,17,9,10,2,6,12,16,15,5,11,18,19,20,21,22,23};
12 int right2[]={0,1,11,5,4,16,12,6,2,9,10,17,13,7,3,15,14,8,18,19,20,21,22,23};//err
13 int temp[24],cube[24],ans,n;
14 void L0(){
15 for(int i=0;i<24;++i) temp[i]=cube[left0[i]];
16 for(int i=0;i<24;++i) cube[i]=temp[i];
17 }
18 void R0(){
19 for(int i=0;i<24;++i) temp[i]=cube[right0[i]];
20 for(int i=0;i<24;++i) cube[i]=temp[i];
21 }
22 void L1(){
23 for(int i=0;i<24;++i) temp[i]=cube[left1[i]];
24 for(int i=0;i<24;++i) cube[i]=temp[i];
25 }
26 void R1(){
27 for(int i=0;i<24;++i) temp[i]=cube[right1[i]];
28 for(int i=0;i<24;++i) cube[i]=temp[i];
29 }
30 void L2(){
31 for(int i=0;i<24;++i) temp[i]=cube[left2[i]];
32 for(int i=0;i<24;++i) cube[i]=temp[i];
33 }
34 void R2(){
35 for(int i=0;i<24;++i) temp[i]=cube[right2[i]];
36 for(int i=0;i<24;++i) cube[i]=temp[i];
37 }
38 int _cpf(int cube[]){
39 int ans=0;
40 for(int i=0;i<6;++i){
41 if(cube[f[i][0]]==cube[f[i][1]]&&cube[f[i][1]]==cube[f[i][2]]&&cube[f[i][2]]==cube[f[i][3]]) ans++;
42 }
43 return ans;
44 }
45 void dfs(int step,int k){
46 ans=max(ans,_cpf(cube));
47 if(step>=n) return ;
48 int tmp[24];
49 for(int i=0;i<24;++i) tmp[i]=cube[i];
50 if(k!=1){
51 L0();dfs(step+1,0);ans=max(ans,_cpf(cube));
52 for(int i=0;i<24;++i) cube[i]=tmp[i];
53 }
54 if(k!=0){
55 R0();dfs(step+1,1);ans=max(ans,_cpf(cube));
56 for(int i=0;i<24;++i) cube[i]=tmp[i];
57 }
58 if(k!=3){
59 L1();dfs(step+1,2);ans=max(ans,_cpf(cube));
60 for(int i=0;i<24;++i) cube[i]=tmp[i];
61 }
62 if(k!=2){
63 R1();dfs(step+1,3);ans=max(ans,_cpf(cube));
64 for(int i=0;i<24;++i) cube[i]=tmp[i];
65 }
66 if(k!=5){
67 L2();dfs(step+1,4);ans=max(ans,_cpf(cube));
68 for(int i=0;i<24;++i) cube[i]=tmp[i];
69 }
70 if(k!=4){
71 R2();dfs(step+1,5);ans=max(ans,_cpf(cube));
72 for(int i=0;i<24;++i) cube[i]=tmp[i];
73 }
74 }
75 int main(){
76 while(~scanf("%d",&n)){
77 for(int i=0;i<24;++i){
78 scanf("%d",cube+i);
79 }
80 ans=0;
81 dfs(0,-1);
82 printf("%d\n",ans);
83 }
84 return 0;
85 }

hdu4801 PocketCube 2阶魔方的更多相关文章

  1. 任意阶魔方阵(幻方)的算法及C语言实现

    写于2012.10: 本来这是谭浩强那本<C程序设计(第四版)>的一道课后习题,刚开始做得时候去网上找最优的算法,结果发现奇数和双偶数(4的倍数)的情况下算法都比较简单,但是单偶数(2的倍 ...

  2. 【C++小白成长撸】--(续)单偶数N阶魔方矩阵

    1 /*程序的版权和版本声明部分: **Copyright(c) 2016,电子科技大学本科生 **All rights reserved. **文件名:单偶数N阶魔方矩阵 **程序作用:单偶数N阶魔 ...

  3. n阶魔方阵(奇数阵)的输出

    需求 要求输出1~n²的自然数构成的魔方阵. STEP 1 什么是魔方阵? 魔方阵,古代又称“纵横图”,是指组成元素为自然数1.2…n2的平方的n×n的方阵,其中每个元素值都不相等,且每行.每列以及主 ...

  4. HDU 1998 奇数阶魔方【模拟填数/注意边界和细节】

    奇数阶魔方 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  5. 算法:九宫格问题--奇数阶魔方(Magic-Square)

    一.魔方介绍 魔方(这里是简称,也可以叫幻方.魔术矩阵,Magic Square)是 n×n 正方形网格(n 为每侧的单元数),里面每个单元格填充了不同的正整数 1, 2, 3, ... , n2,并 ...

  6. 杭电ACM 1998奇数阶魔方

    #include<stdio.h>#include <string.h>int main(){ int n,m; int a[40][40]={0}; scanf(" ...

  7. hdoj 2183 奇数阶魔方(II) 【模拟】+【法】

    比赛的时候花了一个多小时,以做不做 分析:可观察:中间是(n*n+1)/2, 中间的上面是n*n,以下是1, 左边是n,右面是(n*n+1)-n,并且正对角线是最左上对到最右下端添加(+1).另外一条 ...

  8. hdu 1998 奇数阶魔方(找规律+模拟)

    应该不算太水吧. 17  24   1   8  15   23   5   7  14  16    4   6  13  20  22   10  12  19  21   3   11  18 ...

  9. 【ACM】魔方十一题

    0. 前言打了两年的百度之星,都没进决赛.我最大的感受就是还是太弱,总结起来就是:人弱就要多做题,人傻就要多做题.题目还是按照分类做可能效果比较好,因此,就有了做几个系列的计划.这是系列中的第一个,解 ...

随机推荐

  1. LSTM+CRF进行序列标注

    为什么使用LSTM+CRF进行序列标注 直接使用LSTM进行序列标注时只考虑了输入序列的信息,即单词信息,没有考虑输出信息,即标签信息,这样无法对标签信息进行建模,所以在LSTM的基础上引入一个标签转 ...

  2. PAT练习num2-挖掘机技术哪家强

    为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛.现请你根据比赛结果统计出技术最强的那个学校. 输入格式: 输入在第 1 行给出不超过 1 的正整数 N,即参赛人数.随后 N 行, ...

  3. 【原创】Linux虚拟化KVM-Qemu分析(八)之virtio初探

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  4. 笔记 | pandas之时间序列学习随笔1

    1. 时间序列自动生成 ts = pd.Series(np.arange(1, 901), index=pd.date_range('2010-1-1', periods=900)) 最终生成了从20 ...

  5. ATtiny3217 x WS2812B梦幻联动

    TinyAVR 1-series是Microchip于2018年推出的AVR单片机系列,定位是新一代的8位单片机,ATtiny3217是其中最高端的一款.相比于ATmega328P那个时代的AVR,A ...

  6. python_mmdt:从0到1--实现简单恶意代码分类器(二)

    概述 上篇文章python_mmdt:一种基于敏感哈希生成特征向量的python库(一)我们介绍了一种叫mmdt_hash(敏感哈希)生成方法,并对其中的概念做了基本介绍.本篇,我们重点谈谈mmdt_ ...

  7. JavaScript中原型对象的应用!

    JavaScript中原型对象的应用! 扩展内置对象的方法 我以数组对象为例! // 原型对象的应用 扩展内置对象方法! Array.prototype.sum = function() { var ...

  8. Java编程技术之浅析SPI服务发现机制

    SPI服务发现机制 SPI是Java JDK内部提供的一种服务发现机制. SPI->Service Provider Interface,服务提供接口,是Java JDK内置的一种服务发现机制 ...

  9. 奇艺iOS移动端网络优化实践 | 请求成功率优化篇 原创 Charles 爱奇艺技术

    奇艺iOS移动端网络优化实践 | 请求成功率优化篇 原创 Charles 爱奇艺技术

  10. http的响应码及含义

    1xx(临时响应) 100: 请求者应当继续提出请求. 101(切换协议) 请求者已要求服务器切换协议,服务器已确认并准备进行切换. 2xx(成功) 200:正确的请求返回正确的结果 201:表示资源 ...