Colored Cubes UVA - 1352(典型的一种排列枚举)

本文分享了如何通过旋转立方体和深度优先搜索策略,找出最少颜色涂装所有立方体的方法。通过列举所有可能的正方体姿态,并进行遍历,找到使所有立方体颜色相同的最省方案。

Colored Cubes UVA - 1352

题意:

有n个带颜色的立方体,你可以任意旋转,之后涂最少的颜色,使得所有正方体相同。

思路:

  1. 第一个不动,其他旋转(一个正方体总共24种姿态)
  2. 之后写dfs并check’
  3. 先打表,打出排列

AC

#include <iostream>
#include <bits/stdc++.h>
#define For(i,x,y) for(int i=(x); i<=(y); i++)
#define fori(i,x,y) for(int i=(x); i<(y); i++)
#define rep(i,y,x) for(int i=(y); i>=(x); i--)
#define mst(x,a) memset(x,a,sizeof(x))
#define pb push_back
#define sz(a) (int)a.size()
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
typedef pair<ll,ll>pai;
int up[]={2,1,5,0,4,3};
int lef[]={4,0,2,3,5,1};
///p[i] represent the position of idex of i.
///0 formal 1 right 2 up 3 bottom 4 left 5 back
void rot(int* T ,int *P){
    int q[6];
    memcpy(q,P,sizeof(q));
    fori(i,0,6)P[i] = T[q[i]];
}
void enumerate_permutations(){
    int p0[6] = {0,1,2,3,4,5};
    printf("int dice24[24][6] = {\n");
    fori(i,0,6){
        int p[6];
        memcpy(p,p0,sizeof(p0));
        if(i==0)rot(up,p);
        if(i==1)rot(lef,p),rot(up,p);
        if(i==3)rot(up,p),rot(up,p);
        if(i==4)rot(lef,p),rot(lef,p),rot(lef,p),rot(up,p);
        if(i==5)rot(lef,p),rot(lef,p),rot(up,p);
        fori(j,0,4){
            printf("{%d,%d,%d,%d,%d,%d},",p[0],p[1],p[2],p[3],p[4],p[5]);
            rot(lef,p);
        }
        printf("\n");
    }
    printf("};\n");
}
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},
};
int dice[4][6];
int n;
map<string,int>id;
vector<string>v;
int idc(char * x){
    string s(x);
    if(id.count(s))return id[s];
    v.pb(s);
    return id[s]=sz(v)-1;
}
int ans;
int r[5];
void check(){
    int res = 0;
    fori(i,0,6){
        int mx = 0, mx_col;
        int cnt[26]{};
        fori(k,0,n){
            int idx = dice24[r[k]][i];
            cnt[dice[k][idx]]++;
            if(mx < cnt[dice[k][idx]])mx = cnt[dice[k][idx]];
        }
        res += n-mx;
    }
    ans = min(ans,res);
}
void dfs(int s){
    if(s==n){
        check();
        return ;
    }
    fori(i,0,24)r[s]=i,dfs(s+1);
}
int main()
{
   // ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
   // enumerate_permutations();
    while(scanf("%d", &n)&&n){
        id.clear(); v.clear();
        char col[30];
        fori(i,0,n)fori(j,0,6)scanf("%s", col),dice[i][j] = idc(col);
        ans = n*6;
        r[0] = 0;
        dfs(1);
        printf("%d\n", ans);//cout<<ans<<'\n';
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值