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(模拟+置换)

时间: 2024-08-12 16:33:23

uva 1156 - Pixel Shuffle(模拟+置换)的相关文章

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

Description Shuffling the pixels in a bitmap image sometimes yields random looking images. However, by repeating the shuffling enough times, one finally recovers the original images. This should be no surprise, since ``shuffling" means applying a one

uva 10710 - Chinese Shuffle(完美洗牌)

题目链接:uva 10710 - Chinese Shuffle 题目大意:给出n张牌,按照顺序排列好,进行n-1次完美洗牌,问是否可以变成原来德序列. 解题思路:根据完美洗牌的性质,于是第x张牌经过p次后德位置有x?2p,于是只需要证明第1张牌最后是否在远处即可. #include <cstdio> #include <cstring> typedef long long ll; ll pow_mod(ll a, ll n, ll mod) { ll ans = 1; while

UVA - 10733 The Colored Cubes (置换)

All 6 sides of a cube are to becoated with paint. Each side is is coated uniformly with one color. When a selectionof n different colors of paint is available, how many different cubes can youmake? Note that any two cubes are onlyto be called "differ

uva 11330 - Andy&#39;s Shoes(置换)

题目链接:uva 11330 - Andy's Shoes 题目大意:小andy有很多鞋,穿完到处丢,后来他把所有鞋都放回鞋架排成一排,保证了鞋的左右交替,但是颜色混了.问说他至少移动多少次可以将鞋分类好. 解题思路:对应奇数位置为左鞋,偶数位置为右鞋,一双鞋只有一只左鞋和一只右鞋,保证不换左变鞋子,以左鞋的位置为基准换右边鞋子,对应右边鞋子的位置即为一个置换,将置换的循环分解为x个互不相干的循环,ans=n-x #include <cstdio> #include <cstring&g

uva 716 - Commedia dell&#39; arte(置换)

题目链接:uva 716 - Commedia dell' arte 题目大意:给定一个三维的八数码,0表示空的位置,问说是否可以排回有序序列. 解题思路:对于n为奇数的情况,考虑三维八数码对应以为状态下去除0的时候逆序对数,偶数的情况下,考虑将0的位置转移到(n,n,n)位置后对应序列的逆序对数.如果逆序对数为偶数即为可以,奇数不可以. #include <cstdio> #include <cstring> #include <algorithm> using na

UVA 11330 - Andy&#39;s Shoes(置换分解)

UVA 11330 - Andy's Shoes 题目链接 题意:andy有很多双鞋子,每双鞋子有一个编号,现在他把鞋子左右左右放回去,可是不能保证所有鞋子左边和右边是同一编号,现在要求用最少的交换次数,使得所有鞋子左右编号相同 思路:置换的分解,固定左边的鞋子,这样右边的鞋子就可以看成是放在哪个位置,然后根据这个求出每个循环的长度,最后每个循环长度-1的总和就是答案 代码: #include <cstdio> #include <cstring> int t, n, vis[10

Uva - 1513 Moive collection ( 模拟栈 + 树状数组基本操作 )

Uva - 1513 Moive collection ( 模拟栈 + 树状数组基本操作 ) 题意: 一个书架,原来所有的书都是按顺序摆好的,书的编号从1开始到n 操作: 取出一本书,统计在这本书之前有多少本书,统计完之后,将这本书放在书架的第一位. 如:  1 2 3 4 5取4   4 1 2 3 5 (取之前,有3本书在4前面,取完后,将4放在栈顶)取4   4 1 2 3 5 (取之前,有0本书在4前面,取完后,将4放在栈顶)取2   2 4 1 3 5 (取之前,有2本书在2前面,取完

uva 12103 - Leonardo&#39;s Notebook(置换)

题目链接:uva 12103 - Leonardo's Notebook 题目大意:给出26个字母的置换,问是否存在一个置换A,使得A2=B 解题思路:将给定置换分解成若干个不相干的循环,当循环的长度n为奇数时,可以由两个循环长度为n的循环的乘积得来,也可以由两个循环长度为2n的拆分而来:对于长度n为偶数的,只能由两个循环长度为2n的拆分而来,所以判断是否存在有循环长度为偶数的个数是奇数个即可. #include <cstdio> #include <cstring> #inclu

LA 3510 (置换 循环分解) Pixel Shuffle

思路挺简单的,题目中的每个命令(包括命令的逆)相当于一个置换. 用O(n2k)的时间复杂度从右往左求出这些置换的乘积A,然后求m使Am = I(I为全等置换) 还是先把A分解循环,m则等于所有循环节长度的最小公倍数. 需要注意的是: 执行命令是从右往左执行的,这是题目中说的=_= 其他命令还好,mix那个命令把我搞得晕头转向,题中给的是反的,我们要反过来求原图像(i, j)在新图像中的位置. 1 #include <cstdio> 2 #include <cstring> 3 #i