uva 1156 - Pixel Shuffle(模拟+置换)

题目链接:uva 1156 - Pixel Shuffle

题目大意:给定一个N*N的黑白位图,有7种操作,并且对应在指令后加上‘-’即为操作的逆,给定N和一系列操作,(从最后一个开始执行),问说这一套指令需要执行多少次才能形成循环。

解题思路:模拟指令执行后获得一个置换,分解成若干的循环,各个循环长度的最小公倍数即使答案。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long ll;
const int maxn = (1<<10) + 5;

int N, s[maxn][maxn], f[maxn][maxn];
int c, v[maxn];

const char sign[maxn][10] = {"id", "id-", "rot", "rot-", "sym", "sym-", "bhsym", "bhsym-", "bvsym",
    "bvsym-", "div", "div-", "mix", "mix-" };

inline int get_sign (char* word) {
    for (int i = 0; i < 14; i++)
        if (strcmp(word, sign[i]) == 0)
            return i;
    return -1;
}

// 逆时针90
void rot (bool flag) {

    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (flag)
                f[i][j] = s[N-1-j][i];
            else
                f[N-1-j][i] = s[i][j];
        }
    }
    memcpy(s, f, sizeof(f));
}

// 水平翻转
void sym () {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++)
            f[i][j] = s[i][N-1-j];
    }
    memcpy(s, f, sizeof(f));
}

// 下一半水平翻转
void bhsym () {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (i >= N/2)
                f[i][j] = s[i][N-1-j];
            else
                f[i][j] = s[i][j];
        }
    }
    memcpy(s, f, sizeof(f));
}

// 下一半垂直翻转
void bvsym () {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (i >= N/2)
                f[i][j] = s[3 * N / 2 - i - 1][j];
            else
                f[i][j] = s[i][j];
        }
    }
    memcpy(s, f, sizeof(f));
}

// 分成两份
void div (bool flag) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (flag) {
                if (i&1)
                    f[i/2 + N/2][j] = s[i][j];
                else
                    f[i/2][j] = s[i][j];
            } else {
                if (i&1)
                    f[i][j] = s[i/2 + N/2][j];
                else
                    f[i][j] = s[i/2][j];
            }
        }
    }
    memcpy(s, f, sizeof(f));
}

void mix (bool flag) {

    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (i&1) {

                if (flag) {
                    if (j&1)
                        f[i][j] = s[i][N/2 + j/2];
                    else
                        f[i][j] = s[i-1][N/2 + j/2];
                } else {
                    if (j&1)
                        f[i][N/2+j/2] = s[i][j];
                    else
                        f[i-1][N/2+j/2] = s[i][j];
                }
            } else {

                if (flag) {
                    if (j&1)
                        f[i][j] = s[i+1][j/2];
                    else
                        f[i][j] = s[i][j/2];
                } else {
                    if (j&1)
                        f[i+1][j/2] = s[i][j];
                    else
                        f[i][j/2] = s[i][j];
                }
            }
        }
    }

    /* if (N&1) { for (int i = 0; i < N; i++) { f[i][n] = s[i][n]; f[n][i] = s[n][i]; } } */
    memcpy(s, f, sizeof(f));
}

void put () {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++)
            printf("%d ", s[i][j]);
        printf("\n");
    }
}

void handle () {
    for (int i = c-1; i >= 0; i--) {
        switch (v[i]) {
            case 0:
            case 1:
                break;
            case 2:
                rot(true);
                break;
            case 3:
                rot(false);
                break;
            case 4:
            case 5:
                sym();
                break;;
            case 6:
            case 7:
                bhsym();
                break;
            case 8:
            case 9:
                bvsym();
                break;
            case 10:
                div(true);
                break;
            case 11:
                div(false);
                break;
            case 12:
                mix(true);
                break;
            case 13:
                mix(false);
                break;
        }
    }
}

ll gcd (ll a, ll b) {
    return b == 0 ? a : gcd(b, a % b);
}

ll lcm (ll a, ll b) {
    return a / gcd (a, b) * b;
}

ll solve () {
    char str[maxn], word[maxn];
    gets(str);
    int len = strlen(str), mv = 0;

    c = 0;
    for (int i = 0; i <= len; i++) {
        if ((str[i] >= 'a' && str[i] <= 'z') || str[i] == '-')
            word[mv++] = str[i];
        else {
            word[mv] = '\0';
            v[c++] = get_sign(word);
            mv = 0;
        }
    }

    handle();

    ll ret = 1;
    memset(f, 0, sizeof(f));

    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (f[i][j])
                continue;

            int x = s[i][j] / N;
            int y = s[i][j] % N;
            ll cnt = 0;

            while (f[x][y] == 0) {
                f[x][y] = 1;
                cnt++;

                int tmp = s[x][y];
                x = tmp / N;
                y = tmp % N;
            }

            ret = lcm(ret, cnt);
        }
    }

    return ret;
}

int main () {
    int cas;
    scanf("%d", &cas);
    while (cas--) {
        scanf("%d%*c", &N);
        for (int i = 0; i < N; i++)
            for (int j = 0; j < N; j++)
                s[i][j] = i * N + j;
        printf("%lld\n", solve());
        if (cas)
            printf("\n");
    }
    return 0;
}

你可能感兴趣的:(uva 1156 - Pixel Shuffle(模拟+置换))