LA 3401 彩色的立方体(暴力+打表)

题目:https://vjudge.net/problem/UVALive-3401

学习了如何用机器人中的术语“姿态”,来解决这个问题。

一个正方体6个面,当为每个面标上号的时候,这个正方体就有了24种姿态,即每个面作为顶面,每个面作为顶面的时候有4种不同的情况。

这样颜色在不同姿态上的正方体的情况可以看做是互不相同的了。

这道题的实现比较复杂,而且用到了很多技巧。

此外,一定要搞清楚p[i]表示的是什么,书上给的是p[i]表示编号为i的面被转到了第几个面上,

我更喜欢的理解是哪个面现在把编号为i的面给占了。

left []={4,0,2,3,5,1}; 表示编号为0的面现在被4的面占了,编号为1的面被0占了,依次类推,也就是相当于

把正方体左转了一遍。

所以才有了p[i]=T[q[i]]表示编号为i的面被转到了哪个面。

如果按照我的理解方式,可以把up[]改成{3,1,0,5,4,2};

效果是一模一样的(亲试),其实现在的up实际已经变成了down,为了和书上统一,我还是用up了。

首先用打表的方法,把每个24个姿态打印到一个文件里。

打表实现:

#include<bits/stdc++.h>
#include<iostream> 
using namespace std;
                          
int left1[]={4,0,2,3,5,1};      //left1[q[i]]表示让编号为q[i]的面去哪个面 
int up[]={2,1,5,0,4,3};

void rot(int* T,int *p){
	int q[6];
	memcpy(q,p,sizeof(q));
	for(int i=0;i<6;i++)
	p[i]=T[q[i]];
}
void enumerate_permutations(){
	int p0[]={0,1,2,3,4,5};
//	printf("int dice24[24][6]={\n");
	
	ofstream out("C://Users//asus//Desktop//算法.txt");
	out<<"int dice24[24][6]={"<<endl;
	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(left1,p);rot(up,p);}
		if(i==3) {rot(up,p);rot(up,p);}
		if(i==4){rot(left1,p);rot(left1,p);rot(left1,p);rot(up,p);}
		if(i==5){rot(left1,p);rot(left1,p);rot(up,p);}	
		for(int i=0;i<4;i++){
//			printf("{%d %d %d %d %d %d},\n",p[0],p[1],p[2],p[3],p[4],p[5]);
			
			out<<"{"<<p[0]<<", "<<p[1]<<", "<<p[2]<<", "<<p[3]<<", "<<p[4]<<", "<<p[5]<<"},"<<endl;
			rot(left1,p);
		}
	}
//	printf("};\n");
			out<<"};"<<endl;
}

int main(){

	enumerate_permutations();
	return 0; 
	
}

之后,把姿态写入到程序中来,

按照每个正方体的不同姿态进行比对。

#include<bits/stdc++.h>
using namespace std;
int dice24[24][6]={
{2, 1, 5, 0, 4, 3},
{2, 0, 1, 4, 5, 3},
{2, 4, 0, 5, 1, 3},
{2, 5, 4, 1, 0, 3},
{4, 2, 5, 0, 3, 1},
{5, 2, 1, 4, 3, 0},
{1, 2, 0, 5, 3, 4},
{0, 2, 4, 1, 3, 5},
{0, 1, 2, 3, 4, 5},
{4, 0, 2, 3, 5, 1},
{5, 4, 2, 3, 1, 0},
{1, 5, 2, 3, 0, 4},
{5, 1, 3, 2, 4, 0},
{1, 0, 3, 2, 5, 4},
{0, 4, 3, 2, 1, 5},
{4, 5, 3, 2, 0, 1},
{1, 3, 5, 0, 2, 4},
{0, 3, 1, 4, 2, 5},
{4, 3, 0, 5, 2, 1},
{5, 3, 4, 1, 2, 0},
{3, 4, 5, 0, 1, 2},
{3, 5, 1, 4, 0, 2},
{3, 1, 0, 5, 4, 2},
{3, 0, 4, 1, 5, 2},
};
vector<string> names;
const int maxn=4;
int dice[maxn][6];            //表示第几个正方体的哪个面的颜色 
int r[maxn],ans,n;

int id(char *name){
	string s(name);
	int n=names.size();
	for(int i=0;i<names.size();i++)
		if(names[i]==s)
		return i;
	names.push_back(s);
	return n;
}

int color[maxn][6];

void check(){
	for(int i=0;i<n;i++)
	for(int j=0;j<6;j++)
	color[i][dice24[r[i]][j]]=dice[i][j]; //正方体中第几个姿态的哪个面的颜色 

	int tot=0;                            //用来统计需要替换的颜色 
	for(int j=0;j<6;j++){
		int cnt[maxn*6];
		memset(cnt,0,sizeof(cnt));
		int maxface=0;
		for(int i=0;i<n;i++)
		maxface=max(maxface,++cnt[color[i][j]]);
	
		tot+=n-maxface;
	}
		ans=min(ans,tot);
	
}


void dfs(int d){
	if(d==n) check();
	else{	
		for(int i=0;i<24;i++){
			r[d]=i;             //表示第d个正方体的第i种姿态 
			dfs(d+1);		
		}	
	}
}
 

int main(){

	while(scanf("%d",&n) && n){
		names.clear();
		for(int i=0;i<n;i++)
		for(int j=0;j<6;j++){
			char name[30];
			scanf("%s",name);
			dice[i][j]=id(name);			
		}
		ans=n*6;
		r[0]=0;
		dfs(1);
		printf("%d\n",ans);
	}
	return 0;
}

 

 

发布了57 篇原创文章 · 获赞 58 · 访问量 624

猜你喜欢

转载自blog.csdn.net/weixin_43568895/article/details/103757309