Codeforces Gym 101505(2016-2017 CTU Open Contest) D---群论、模拟

题意:给一个N*N矩阵,里面的图形有x,o,<,>,v,^,|,-,/,\ 要求你按照指定的操作顺序进行旋转和轴对称后,输出矩阵最终的形态
分析:如果直接暴力模拟,复杂度达到100*100*操作步数,会T。分析后可以得知,无论怎么变换,其最终形态必然只有8种可能,同构于正方形变换群,可以大致写一下:(用1234编号正方形的四个角)
这里写图片描述

然后只需要对正方形变换群进行操作,大大降低了每一次操作的复杂度,最后再将变换运用到原来的矩阵上,模拟还是比较麻烦的。
AC代码:

#include <bits/stdc++.h>
using namespace std;
#define mem(s,v) memset(s,v,sizeof(s))
typedef long long ll;
typedef long double ld;
const double PI = acos(-1);
const ll MOD = 2147493647;
const int inf = 0x3f3f3f3f;
const ll INF =  0x3f3f3f3f3f3f3f3f;

int b[8][2][2];

int get(int g[2][2]){
    for(int i = 0;i<8;i++){
        bool f = 1;
        for(int j = 0;j<2;j++){
            for(int k = 0;k<2;k++){
                if(b[i][j][k]!=g[j][k]) f = 0;
            }
        }
        if(f) return i;
    }
}
//int o(int i,int j){
//    if(i==0&&j==0) return 1;
//    if(i==0&&j==1) return 2;
//    if(i==1&&j==1) return 3;
//    if(i==1&&j==0) return 4;
//}
int a[2];
void o(int x){
    if(x==1){
        a[0] = 0,a[1] = 0;
    }
    if(x==2){
        a[0] = 0,a[1] = 1;
    }
    if(x==3){
        a[0] = 1,a[1] = 1;
    }
    if(x==4){
        a[0] = 1,a[1] = 0;
    }
}

int g[2][2];
void add(int f[2][2],int p){
    int t[2];
    for(int i = 0;i<2;i++){
        for(int j = 0;j<2;j++){
            o(b[p][i][j]);
            g[i][j] = f[a[0]][a[1]];
        }
    }
}
int n;
char st[105][105];
char ans[105][105];
string s;

int op(char c){
    if(c=='>')return 1;
    if(c=='<')return 3;
    if(c=='|')return 4;
    if(c=='-')return 5;
    if((int)c==92)return 6;
    if(c=='/')return 7;
}


int x,y;
char ok(char c,int d,int i,int j){
    if(d==0){
        x = i;y = j;
        return c;
    }
    if(d==1){
        x = j;y = n-1-i;
        if(c=='>') return 'v';
        if(c=='<') return '^';
        if(c=='v') return '<';
        if(c=='^') return '>';
        if(c=='|') return '-';
        if(c=='-') return '|';
        if(c=='/') return (char)92;
        if((int)c==92) return '/';
    }
    if(d==2){
        x = n-1-i;y = n-1-j;
        if(c=='>') return '<';
        if(c=='<') return '>';
        if(c=='v') return '^';
        if(c=='^') return 'v';
        if(c=='|') return '|';
        if(c=='-') return '-';
        if(c=='/') return c;
        if((int)c==92) return c;

    }
    if(d==3){
        y = i;x = n-1-j;
        if(c=='>') return '^';
        if(c=='<') return 'v';
        if(c=='v') return '>';
        if(c=='^') return '<';
        if(c=='|') return '-';
        if(c=='-') return '|';
        if(c=='/') return (char)92;
        if((int)c==92) return '/';
    }
    if(d==4){
        x = i;y = n-1-j;
        if(c=='>') return '<';
        if(c=='<') return '>';
        if(c=='v') return 'v';
        if(c=='^') return '^';
        if(c=='|') return c;
        if(c=='-') return c;
        if(c=='/') return (char)92;
        if((int)c==92) return '/';
    }
    if(d==5){
        x = n-1-i;y = j;
        if(c=='>') return c;
        if(c=='<') return c;
        if(c=='v') return '^';
        if(c=='^') return 'v';
        if(c=='|') return c;
        if(c=='-') return c;
        if(c=='/') return (char)92;
        if((int)c==92) return '/';
    }
    if(d==6){
        x = j;y = i;
        if(c=='>') return 'v';
        if(c=='<') return '^';
        if(c=='v') return '>';
        if(c=='^') return '<';
        if(c=='|') return '-';
        if(c=='-') return '|';
        if(c=='/') return c;
        if((int)c==92) return c;
    }
    if(d==7){
        x = n-1-j;y = n-1-i;
        if(c=='>') return '^';
        if(c=='<') return 'v';
        if(c=='v') return '<';
        if(c=='^') return '>';
        if(c=='|') return '-';
        if(c=='-') return '|';
        if(c=='/') return c;
        if((int)c==92) return c;
    }
    if(c=='x'||c=='o'){
        return c;
    }
}
int main(){
    //std::ios::sync_with_stdio(false);
    b[0][0][0] = 1;b[0][0][1] = 2;b[0][1][1] = 3;b[0][1][0] = 4;
    b[1][0][0] = 4;b[1][0][1] = 1;b[1][1][1] = 2;b[1][1][0] = 3;
    b[2][0][0] = 3;b[2][0][1] = 4;b[2][1][1] = 1;b[2][1][0] = 2;
    b[3][0][0] = 2;b[3][0][1] = 3;b[3][1][1] = 4;b[3][1][0] = 1;
    b[4][0][0] = 2;b[4][0][1] = 1;b[4][1][1] = 4;b[4][1][0] = 3;
    b[5][0][0] = 4;b[5][0][1] = 3;b[5][1][1] = 2;b[5][1][0] = 1;
    b[6][0][0] = 1;b[6][0][1] = 4;b[6][1][1] = 3;b[6][1][0] = 2;
    b[7][0][0] = 3;b[7][0][1] = 2;b[7][1][1] = 1;b[7][1][0] = 4;

    while(cin>>n){
        for(int i = 0;i<n;i++){
            cin>>st[i];getchar();
        }
        getline(cin,s);
        int l = s.size();
        int f[2][2];
        f[0][0] = 1;f[0][1] = 2;f[1][1] = 3;f[1][0] = 4;
        for(int i = 0;i<l;i+=2){
            add(f,op(s[i]));
            for(int ii = 0;ii<2;ii++){
                for(int jj = 0;jj<2;jj++){
                    f[ii][jj] = g[ii][jj];
                }
            }
        }
        int res = get(f);
        //cout<<res<<endl;
        for(int i = 0;i<n;i++){
            for(int j = 0;j<n;j++){
                x = i,y = j;
                char tmp = ok(st[i][j],res,i,j);
                ans[x][y] = tmp;
            }
        }
        for(int i = 0;i<n;i++){
            for(int j = 0;j<n;j++){
                cout<<ans[i][j];
            }
            cout<<endl;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值