LA 3401 Colored Cubes

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

题目

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值