USACO3.2.4 mequare

2017年5月6日 | ljfcnyali
题目大意
在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。这是一张有8个大小相同的格子的魔板:
1 2 3 4
8 7 6 5
我们知道魔板的每一个方格都有一种颜色。这8种颜色用前8个正整数来表示。可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。对于上图的魔板状态,我们用序列(1,2,3,4,5,6,7,8)来表示。这是基本状态。
这里提供三种基本操作,分别用大写字母“A”,“B”,“C”来表示(可以通过这些操作改变魔板的状态):
“A”:交换上下两行;
“B”:将最右边的一列插入最左边;
“C”:魔板中央四格作顺时针旋转。
下面是对基本状态进行操作的示范:
A: 8 7 6 5
1 2 3 4
B: 4 1 2 3
5 8 7 6
C: 1 7 2 4
8 6 3 5
对于每种可能的状态,这三种基本操作都可以使用。
你要编程计算用最少的基本操作完成基本状态到目标状态的转换,输出基本操作序列。

Sample Input

2 6 8 4 5 7 3 1 

Sample Output

7 
BCABCCB

题目分析
BFS水过!

AC代码

/*
ID: jerry272
PROG: msquare
LANG: C++
*/
#include<iostream>
#include<cstdio>
#include<set>
#include<cstring>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<map>

#define to(a,b,c,d,e,f,g,h) (((long long)(a)<<0)|((long long)(b)<<8)|((long long)(c)<<16)|((long long)(d)<<24)|((long long)(e)<<32)|((long long)(f)<<40)|((long long)(g)<<48)|(long long)(h)<<56) 
#define REP(i, a, b) for ( int i = (a), _end_ = (b); i <= _end_; ++ i)
#define mem(a) memset ( (a), 0, sizeof (a))
#define str(a) strlen (a);

using namespace std;

long long num[]={0x00000000000000FFLL,0x000000000000FF00LL,0x0000000000FF0000LL,0x00000000FF000000LL,0x000000FF00000000LL,0x0000FF0000000000LL,0x00FF000000000000LL,0xFF00000000000000LL};

struct node{
    long long status;
    string str; 
}st, ans;

int s[8], tmp[8];

long long ed = to(1, 2, 3, 4, 5, 6, 7, 8);

queue <node> Q;

set <long long> S;

int f;

void bfs() {
    while(!Q.empty()) 
        Q.pop();
    long long ed = to(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]);
    st.status = to(1, 2, 3, 4, 5, 6, 7, 8);
    st.str = ""; 
    Q.push(st);
    S.clear();
    while(!Q.empty()){
        struct node now = Q.front();
        Q.pop();
        if(S.count(now.status) > 0) 
            continue; 
        if(ed == now.status) {
            ans = now;
            return;
        }
        S.insert(now.status);
        REP(i, 0, 7) 
            s[i] = ((num[i] & now.status) >> i * 8);
        swap(s[0], s[7]);
        swap(s[1], s[6]);
        swap(s[2], s[5]);
        swap(s[3], s[4]);
        //A
        struct node temp;
        temp.status = to(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]);
        temp.str = now.str + "A"; 
        Q.push(temp);
        swap(s[0], s[7]);
        swap(s[1], s[6]);
        swap(s[2], s[5]);
        swap(s[3], s[4]);
        //A
        swap(s[0], s[1]);
        swap(s[7], s[6]);
        //B
        swap(s[0], s[2]);
        swap(s[7], s[5]);
        swap(s[0], s[3]);
        swap(s[7], s[4]);
        temp.status = to(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]);
        temp.str = now.str + "B";
        Q.push(temp);
        REP(i, 0, 7) 
            s[i] = ((num[i] & now.status) >> i * 8);
        swap(s[1], s[2]);
        swap(s[1], s[5]);
        swap(s[1], s[6]);
        //C
        temp.status = to(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]);
        temp.str = now.str + "C";
        Q.push(temp);
    }
}

int main() {
    freopen("msquare.in", "r", stdin);
    freopen("msquare.out", "w", stdout);
    int t;
    REP(i, 0, 7)
       scanf("%d", &s[i]);
    bfs();
    cout << ans.str.size() << endl;
    cout << ans.str << endl;
}

本文转自:http://ljf-cnyali.cn/index.php/archives/138

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值