hdu4801 PocketCube 2阶魔方

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 }

时间: 2024-10-27 06:37:11

hdu4801 PocketCube 2阶魔方的相关文章

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

1 /*程序的版权和版本声明部分: 2 **Copyright(c) 2016,电子科技大学本科生 3 **All rights reserved. 4 **文件名:单偶数N阶魔方矩阵 5 **程序作用:单偶数N阶魔方矩阵 6 **作者:Amoshen 7 **完成日期:2016.11.2 8 **版本号:V1.0 9 */ 10 #include<iostream> 11 12 using namespace std; 13 14 #define MAX_SIZE 100 15 16 int

魔方游戏实现(一):任意阶魔方的表示

 第一节 魔方的简单表示 对于任意N阶的魔方均有六个面(Surface),每个面有N*N个方块.在面向对象的程序设计里,我们可以把魔方(Cube).魔方的面(Surface)和面的方块(Block)均视作为对象. 魔方的定义:六个面存储在一个数组 ''' <summary> ''' 表示一个指定阶的魔方 ''' </summary> Public Class CubeClass ''' <summary> ''' 魔方阶数 ''' </summary> Pu

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

写于2012.10: 本来这是谭浩强那本<C程序设计(第四版)>的一道课后习题,刚开始做得时候去网上找最优的算法,结果发现奇数和双偶数(4的倍数)的情况下算法都比较简单,但是单偶数(2的倍数但不是4的倍数)情况一直找不到明确的算法,就连百度百科对这一问题的解释也是“因非四的倍数作法相当复杂,在此只介绍四的倍数的作法”,而且连谭浩强那本书给的答案中竟然也变相的限定了n只能为奇数(题目并未说明).在广泛查找资料后,发现了一篇由中南大学信息科学与工程学院某教授和研究生撰写的论文,介绍了任意阶幻方的算

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

需求 要求输出1~n2的自然数构成的魔方阵. STEP 1 什么是魔方阵? 魔方阵,古代又称"纵横图",是指组成元素为自然数1.2-n2的平方的n×n的方阵,其中每个元素值都不相等,且每行.每列以及主.副对角线上各n个元素之和都相等. STEP 2 魔方阵的规律是什么? 此处先写简单一点的奇阶魔方阵,偶数阶的算法更复杂,暂不讨论. 奇阶魔方阵的排列方法: ⑴将1放在第一行中间一列: ⑵从2开始直到n×n止各数依次按下列规则存放:每一个数存放的行比前一个数的行数减1,列数加1: ⑶如果上

Hdu 1998 奇数阶魔方

奇数阶魔方 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4629    Accepted Submission(s): 2622 Problem Description 一个 n 阶方阵的元素是1,2,...,n^2,它的每行,每列和2条对角线上元素的和相等,这样的方阵叫魔方.n为奇数时我们有1种构造方法,叫做"右上方" ,

奇数阶魔方 NYOJ 734

#include<stdio.h>//奇数阶魔方(734) int main() { int a[20][20],i,j,n,x,cnt; scanf("%d",&x); while(x--){ scanf("%d",&n); for(i=0;i<n;i++){ for(j=0;j<n;j++){ a[i][j]=0; } } a[0][n/2]=1; i=0;j=n/2; cnt=1; while(cnt<=n*n){

奇数阶魔方问题

问题: 一个 n 阶方阵的元素是1,2,...,n^2,它的每行,每列和2条对角线上元素的和相等,这样的方阵叫魔方.n为奇数时我们有1种构造方法,叫做“右上方” ,例如下面给出n=3,5,7时的魔方.38 1 63 5 74 9 2517 24 1 8 1523 5 7 14 164 6 13 20 2210 12 19 21 311 18 25 2 9730 39 48 1 10 19 2838 47 7 9 18 27 2946 6 8 17 26 35 375 14 16 25 34 36

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

一.魔方介绍 魔方(这里是简称,也可以叫幻方.魔术矩阵,Magic Square)是 n×n 正方形网格(n 为每侧的单元数),里面每个单元格填充了不同的正整数 1, 2, 3, ... , n2,并且每一行.每一列和对角线中的正整数之和相等.每行.每列以及对角线上的单元格里的正整数之和又叫做魔术常数或魔方的魔术和. 幻方历史: <系辞>云:“河出图,洛出书,圣人则之.”在宋朝之前,洛书的记述只有文字. 九宫图实物最早发现于西汉,1977年中国考古学家在安徽阜阳县双古堆西汉古墓中发现汉文帝七年

hdoj 2183 奇数阶魔方(II) 【模拟】+【规律】

比赛的时候花了一个多小时还是没做出来 分析:观察得到:最中间是(n*n+1)/2, 中间的上面是n*n,下面是1, 左边是n,右面是(n*n+1)-n,而且正对角线是最左上对到最右下端增加(+1),另外一条对角线是最右上到最左下递减(-n) ,其他对角线也是这样的规律. 难点:模拟的时候数据有点杂,很容易搞错,要细心点. 心得:做题的时候要先确定思路是正确的,并且要履好思路之后在敲代码. 代码: #include <cstdio> #include <cstring> int s[