题目
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=30485
题解
本来这道题一开始分析的时候有两种想法,第一是枚举每个立方体每个面的颜色,统计需要变换的个数,粗略统计,复杂度在O(24^24* n*6),必T无疑.第二种是枚举每个正方体的朝向,算了算,以某一面为基准,这个面本身有6种情况,确定这个面之后有4种情况(就把侧面转一转),总共24种,但是我一煞笔就想到4个都需要枚举,复杂度是O(24^4),粗略估计TLE。然后我就不明白啦,这n<=4的题都能把我卡住了?想了两个小时确实没想出什么有用的办法。无奈还是看题解。然后我发现了interesting的事情,先是24种情况打表,便于找出对应关系,比如说cell[3][2]就表示在第3种姿态中的2号面是输入时的几号面(输入时的姿态定为1号)。更关键的是我忽略了第一个其实根本不用转!物理老师告诉我们运动是相对的,所以选择第一个作为参考系不就好了?时间复杂度降为O(24^3),完全可以AC。
其实之前那道雕塑的题就引入了参考系这个看似是一个猜想的东西,这里得到实际应用,自己思维上还存在缺陷,本来马上就做出来的题却遗憾的挂成暴力,如果在NOI赛场上,是一种多么痛的领悟。(这道题看着麻烦但是代码并不长)
代码
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=10;
const int INF=(1<<30);
const int cell[][6]={{},
{1,2,3,4,5,6},{1,4,2,5,3,6},{1,5,4,3,2,6},{1,3,5,2,4,6},
{3,2,6,1,5,4},{3,1,2,5,6,4},{3,5,1,6,2,4},{3,6,5,2,1,4},
{6,2,4,3,5,1},{6,3,2,5,4,1},{6,5,3,4,2,1},{6,4,5,2,3,1},
{2,1,4,3,6,5},{2,3,1,6,4,5},{2,6,3,4,1,5},{2,4,6,1,3,5},
{5,1,3,4,6,2},{5,4,1,6,3,2},{5,6,4,3,1,2},{5,3,6,1,4,2},
{4,1,5,2,6,3},{4,2,1,6,5,3},{4,6,2,5,1,3},{4,5,6,1,2,3}
};
int n,id_cnt=0,ans=0,rot[maxn],col[maxn][maxn];
map<string,int>id;
string tmp;
int cnt[maxn*6];
void DFS(int cur)
{
if(cur!=n+1)
{
for(int i=1;i<=24;i++)
rot[cur]=i,DFS(cur+1);
return ;
}
int sum=0;
for(int i=1;i<=6;i++)
{
memset(cnt,0,sizeof(cnt));
int maxnum=0;
for(int k=1;k<=n;k++)
{
maxnum=max(maxnum,++cnt[col[k][cell[rot[k]][i-1]]]);
}
sum+=n-maxnum;
}
ans=min(ans,sum);
}
inline void solve()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=6;j++)
{
cin>>tmp;
if(!id.count(tmp)) id[tmp]=++id_cnt;
col[i][j]=id[tmp];
}
ans=INF;
memset(rot,0,sizeof(rot));
rot[1]=1;
if(n==1) printf("0\n");
else DFS(2),printf("%d\n",ans);
}
int main()
{
while(scanf("%d",&n)==1&&n) solve();
return 0;
}

本文探讨了一道关于正方体颜色匹配的问题,通过引入参考系的概念,将原始的高复杂度问题简化到了可接受范围内,并给出了具体的实现代码。

347

被折叠的 条评论
为什么被折叠?



