Sicily 2011. Nine Digits

时间:2015-03-30 09:20:39   收藏:0   阅读:104

2011. Nine Digits

Constraints

Time Limit: 2 secs, Memory Limit: 256 MB

Description

 Nine tiles, each with a number from 1 to 9 on it, are packed into a 3 by 3 frame. Your task is to arrange the tiles so that they are ordered as:

1 2 3
4 5 6
7 8 9
 
       At each step, you can do the following operation to the tiles: Choose 2 by 2 tiles, rotate the tiles in clockwise order. For example:
       1 2 3             4 1 3                           1 2 3             1 2 3
       4 5 6      =>   5 2 6             or           4 5 6      =>   4 8 5
       7 8 9             7 8 9                           7 8 9             7 9 6
 

       Write a program to find the minimum number of steps.

Input

 Input contains multiple test cases.

       Each test case is a description of a configuration of the nine tiles. The description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and from left to right within a row, where the tiles are represented by numbers 1 to 9. For example:
       9 8 7
       6 5 4
       3 2 1
is described by this list:
       9 8 7 6 5 4 3 2 1

Output

 Output the minimum number of steps on a single line for each test case.

Sample Input

1 2 3 4 5 6 7 8 9
4 1 3 5 2 6 7 8 9

Sample Output

0
3

Problem Source

每周一赛:2010中山大学新手赛


相当好的一道题,bfs + 康托,方法是逆序思维,将123456789不断转化为各种排列形式,并记录步数;

但是有个麻烦,想要这样过,就必须用数组存步数,数组是开不了那么大的,这就要用到康托,其实康托就是把排列组合与实数之间建立映射;

#include <iostream>
#include <queue>
#include <stdio.h>
using namespace std;

int fac[9] = {40320, 5040, 720, 120, 24, 6, 2, 1, 1};//阶乘的值,用来康托的
int ans[362880 + 1];//存放答案

int make_num(int a[]) {//将数字数组转化为数字
    int sum = 0;
    for (int i = 0; i < 9; i++) {
        sum = sum * 10 + a[i];
    }
    return sum;
}

void make_permutation(int pre, int a[], int pos) {//读入一个数字,然后返回下一变化的数组
    int i = 8;
    while (pre) {
        a[i--] = pre % 10;
        pre /= 10;
    }
    if (pos == 1) {
        int temp = a[0];
        a[0] = a[1];
        a[1] = a[4];
        a[4] = a[3];
        a[3] = temp;
        return;
    } else if (pos == 2) {
        int temp = a[1];
        a[1] = a[2];
        a[2] = a[5];
        a[5] = a[4];
        a[4] = temp;
        return;
    } else if (pos == 3) {
        int temp = a[3];
        a[3] = a[4];
        a[4] = a[7];
        a[7] = a[6];
        a[6] = temp;
        return;
    } else {
        int temp = a[4];
        a[4] = a[5];
        a[5] = a[8];
        a[8] = a[7];
        a[7] = temp;
        return;
    }
}

int cantor(int a[]) {//康托
    int pos = 0, count, i, j;
    for (i = 0; i < 8; i++) {
        count = 0;
        for (j = i + 1; j < 9; j++) {
            if (a[i] > a[j])
                count++;
        }
        pos += count * fac[i];
    }
    return pos;
}

void bfs() {
    
    queue<int> Q;
    Q.push(123456789);
    int step = 0;
    int i, next[9];
    int pos;
    int now_size;
    
    while (!Q.empty()) {
        
        step++;//每次更新都是要走多一步的
        now_size = Q.size();//记录当前的size,然后走完它(又会生成新的size)
        
        while (now_size--) {
            for (i = 1; i <= 4; i++) {//遍历四种转化
                make_permutation(Q.front(), next, i);
                pos = cantor(next);//通过康托获取位置   
                if (ans[pos] == 0) {//如果为0就是没有用过
                    ans[pos] = step;
                    Q.push(make_num(next));
                }
            }
            Q.pop();//队首已经用过了
        }
    }
    ans[0] = 0;
}
    
int main() {
    bfs();
    int sum[20];
    while(~scanf("%d", &sum[0])) {
        for (int i = 1; i <= 8; i++) {
            scanf("%d", &sum[i]);
        }
        printf("%d\n", ans[cantor(sum)]);
    }
    return 0;
}                  


评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!