Colored Cubes

29 篇文章 0 订阅
6 篇文章 0 订阅

题意:

给出n个带颜色的正方体,求改变最少面的颜色使得所有正方体一样

思路:

以第一个正方体最为基准,通过所有旋转,求出最多重叠面的值

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
#include<string>
using namespace std;
map<string, int> color;
int cube[5][6], now[5][6];
int cnt[25];
int n, ans;
int dir[24][6] = {  
	3,1,0,5,4,2,  
	1,2,0,5,3,4,  
	2,4,0,5,1,3,  
	4,3,0,5,2,1,  
	3,5,1,4,0,2,  
	5,2,1,4,3,0,  
	2,0,1,4,5,3,  
	0,3,1,4,2,5,  
	0,1,2,3,4,5,  
	1,5,2,3,0,4,  
	5,4,2,3,1,0,  
	4,0,2,3,5,1,  
	5,1,3,2,4,0,  
	1,0,3,2,5,4,  
	0,4,3,2,1,5,  
	4,5,3,2,0,1,  
	3,4,5,0,1,2,  
	4,2,5,0,3,1,  
	2,1,5,0,4,3,  
	1,3,5,0,2,4,  
	3,0,4,1,5,2,  
	0,2,4,1,3,5,  
	2,5,4,1,0,3,  
	5,3,4,1,2,0,  
}; 
void dfs(int cur) {
	if(cur >= n) {
		int count = 0;
		for(int i=0; i<6; i++) {
			memset(cnt, 0, sizeof(cnt));
			int tmp = 0;
				for(int j=0; j<n; j++) {
					tmp = max(tmp, ++cnt[now[j][i]]);//最大重叠
				}
				count += (n - tmp);
		}
		ans = min(ans, count);
		return;
	}
	for(int i=0; i<24; i++) {
		for(int j=0; j<6; j++) {
			now[cur][j] = cube[cur][dir[i][j]];
		}
		dfs(cur+1);
	}
}

int main() {
	char c[30];
	while(scanf("%d", &n)!=EOF && n) {
		int id=0;
		color.clear();
		for(int i=0; i<n; i++){
			for(int j=0; j<6; j++) {
				scanf("%s", c);
				if(color.find(c) == color.end())
					color[c] = id++;//给每个颜色唯一的id
				cube[i][j] = color[c];
			}
		}
		ans = 0x3f3f3f3f;
		for(int i=0; i<6; i++) now[0][i] = cube[0][i];//以第一列为基准
		dfs(1);
		printf("%d\n", ans);
	}
	return 0;
}

附带生成旋转面的代码, 一共六个面,每个面作为底面有四种旋转

  
int dice24[24][6] = {  
3,1,0,5,4,2,  
1,2,0,5,3,4,  
2,4,0,5,1,3,  
4,3,0,5,2,1,  
3,5,1,4,0,2,  
5,2,1,4,3,0,  
2,0,1,4,5,3,  
0,3,1,4,2,5,  
0,1,2,3,4,5,  
1,5,2,3,0,4,  
5,4,2,3,1,0,  
4,0,2,3,5,1,  
5,1,3,2,4,0,  
1,0,3,2,5,4,  
0,4,3,2,1,5,  
4,5,3,2,0,1,  
3,4,5,0,1,2,  
4,2,5,0,3,1,  
2,1,5,0,4,3,  
1,3,5,0,2,4,  
3,0,4,1,5,2,  
0,2,4,1,3,5,  
2,5,4,1,0,3,  
5,3,4,1,2,0,  
};  
  
int left[] = {1,5,2,3,0,4};  
int up[] = {3,1,0,5,4,2};  
  
// “旋转”  
void rot(int* T, int* p){  
    int q[6];  
    memcpy(q,p,sizeof(q));  
    for(int i=0; i<6; ++i) p[i] = q[T[i]];  
}  
// 生成旋转序列用的  
void func(){   
    int p0[6] = {0,1,2,3,4,5};  
    printf("int dice24[24][6] = {\n");  
    for(int i=0; i<6; ++i) {  
        int p[6];  
        memcpy(p, p0, sizeof(p0));  
        if(i==0) rot(up, p);  
        if(i==1) { rot(left,p); rot(up, p); }  
        if(i==3) { rot(up,p); rot(up, p); }  
        if(i==4) { rot(left, p); rot(left,p); rot(up,p); }  
        if(i==5) { rot(left, p); rot(left,p); rot(left,p); rot(up,p);}  
        for(int j=0; j<4; ++j){  
            printf("%d,%d,%d,%d,%d,%d,\n",p[0],p[1],p[2],p[3],p[4],p[5]);  
            rot(left,p);  
        }  
          
    }  
    printf("};\n");  
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值