#1240 : Image Encryption 类比矩阵初等变换而来的思路

1
0

写了时间复杂度较小的解法。简单来说,就是把两张图像分别变换成它们的“规范型”。然后,通过比较它们的“规范型”是否相同,来判断两张图像是否可以相互变换。

首先,是把二维的图像数据(Matrix)变换成一维的数组(Stream),以便对其进行旋转。Stream是以旋转的方式排列数据,因而对其进行旋转操作,非常方便和高效。

然后,就是把Stream转换成它的“规范型”(其实就是所有可能的变换结果中字典序最小的变换结果)。具体来说,就是,先把四个子Stream变换成“规范型”,再把它整体进行旋转操作,在所得的四个操作结果中选字典序最小的操作结果作为它的“规范型”。

最后,比较它们的“规范型”,完全相同输出“Yes”,否则,输出“No”。

时间复杂度应该是O(N^2 log N)吧。N是图像边长。

#include <stdio.h>

int N;

struct Pair {
    int x, y;
    Pair() : x(0), y(0) {}
    Pair(int x, int y) : x(x), y(y) {}
    Pair operator + (const Pair & t) const {
        return Pair(x + t.x, y + t.y);
    }
    Pair operator * (const Pair & t) const {
        return Pair(x * t.x - y * t.y, y * t.x + x * t.y);
    }
    Pair & operator += (const Pair & t) {
        return (*this = *this + t);
    }
    Pair & operator *= (const Pair & t) {
        return (*this = *this * t);
    }
};

struct Matrix {
    int n;
    int e[105][105];
    int operator [] (const Pair & p) const {
        return e[p.y][p.x];
    }
} mA, mB;

struct Stream {
    int n;
    int e[105 * 105];
    void initialize(const Matrix & A, Pair Org, Pair V, int M, int N) {
        if(M != N) {
            Pair I;
            for(I.x = 0; I.x < M; ++I.x)
                for(I.y = 0; I.y < N; ++I.y)
                    e[n++] = A[Org + I * V];
            return;
        }
        if(N & 1) {
            e[n++] = A[Org + Pair(N>>1, N>>1) * V];
            int i; Pair I(0, 1);
            for(i=0; i<4; ++i) {
                initialize(A, Org, V, (N>>1)+1, N>>1);
                Org += Pair(N-1, 0) * V;
                V *= I;
            }
            return;
        }
        int i; Pair I(0, 1);
        for(i=0; i<4; ++i) {
            initialize(A, Org, V, N>>1, N>>1);
            Org += Pair(N-1, 0) * V;
            V *= I;
        }
    }
    void initialize(const Matrix & A) {
        n = 0;
        initialize(A, Pair(0, 0), Pair(1, 0), A.n, A.n);
    }
    int t[105 * 105];
    void rotate(int i, int n, int k) {
        if(n & 3) {
            t[i] = e[i];
            ++i;
            --n;
        }
        int j;
        for(j=0; j<n; ++j)
            t[i + (j + (n>>2) * k) % n] = e[i + j];
    }
    int kk, tt[105 * 105];
    void regulate(int i, int n) {
        int j, k;

        if((n & 3) == 0) {
            for(j=0; j<4; ++j)
                regulate(i + (n>>2) * j, n>>2);
        }

        kk = 0;
        for(j=i; j<i+n; ++j) tt[j] = e[j];

        for(k=1; k<4; ++k) {
            rotate(i, n, k);
            for(j=i; j < i+n && t[j] == tt[j]; ++j);
            if(j < i+n && t[j] < tt[j]) {
                kk = k;
                for(j=i; j<i+n; ++j) tt[j] = t[j];
            }
        }

        for(j=i; j<i+n; ++j) e[j] = tt[j];
    }
    void regulate() {
        regulate(0, n);
    }
} sA, sB;

int main() {
    int T;
    scanf("%d", &T);

    int i, j, k;
    for(i=0; i<T; ++i) {
        scanf("%d", &N);
        mA.n = N;
        for(j=0; j<N; ++j)
            for(k=0; k<N; ++k)
                scanf("%d", &mA.e[j][k]);
        mB.n = N;
        for(j=0; j<N; ++j)
            for(k=0; k<N; ++k)
                scanf("%d", &mB.e[j][k]);
        sA.initialize(mA);
        sB.initialize(mB);
        sA.regulate();
        sB.regulate();
        for(j=0; j<N*N && sA.e[j]==sB.e[j]; ++j);
        if(j == N*N) printf("Yes\n");
        else printf("No\n");
    }

    return 0;
}

0 answer(s)

write answer 切换为英文 切换为中文


转发分享