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

思路挺简单的,题目中的每个命令(包括命令的逆)相当于一个置换。

用O(n2k)的时间复杂度从右往左求出这些置换的乘积A,然后求m使Am = I(I为全等置换)

还是先把A分解循环,m则等于所有循环节长度的最小公倍数。

 

需要注意的是:

执行命令是从右往左执行的,这是题目中说的=_=

其他命令还好,mix那个命令把我搞得晕头转向,题中给的是反的,我们要反过来求原图像(i, j)在新图像中的位置。

  1 #include <cstdio>

  2 #include <cstring>

  3 #include <iostream>

  4 #include <string>

  5 #include <sstream>

  6 #include <vector>

  7 using namespace std;

  8 

  9 int gcd(int a, int b)

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

 11 

 12 int lcm(int a, int b)

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

 14 

 15 const int maxn = 1025;

 16 int n;

 17 char s[300], op[35][10];

 18 

 19 inline int ID(int i, int j)

 20 { return i*n + j; }

 21 

 22 int newpos(int i, int j, const char* op)

 23 {

 24      if(op[0] == 'r') return ID(n-j-1, i);

 25      if(op[0] == 's') return ID(i, n-j-1);

 26      if(op[0] == 'b' && op[1] == 'h')

 27      {

 28          if(i >= n/2) return ID(i, n-j-1);

 29          return ID(i, j);

 30      }

 31      if(op[0] == 'b' && op[1] == 'v')

 32      {

 33          if(i >= n/2) return ID(n-(i-n/2)-1, j);

 34          return ID(i, j);

 35      }

 36      if(op[0] == 'd')

 37      {

 38          if(i & 1) return ID(n/2 + i/2 ,j);

 39          return ID(i/2, j);

 40      }

 41      if(op[0] == 'm')

 42      {

 43          int k = i/2;

 44          if(j < n/2) return i % 2 == 0 ? ID(k*2, j*2) : ID(k*2, j*2+1);

 45          else return i % 2 == 0 ? ID(2*k+1, 2*(j-n/2)) : ID(2*k+1, 2*(j-n/2)+1);

 46      }

 47      return ID(i, j);

 48 }

 49 

 50 int cur[maxn * maxn], origin[maxn * maxn];

 51 

 52 void apply(const char* op)

 53 {

 54     for(int i = 0; i < n*n; i++) origin[i] = cur[i];

 55     bool inv = op[strlen(op)-1] == '-' ? true : false;

 56     for(int i = 0; i < n; i++)

 57         for(int j = 0; j < n; j++)

 58         {

 59             int p = ID(i, j), p2 = newpos(i, j, op);

 60             if(inv) cur[p] = origin[p2];

 61             else cur[p2] = origin[p];

 62         }

 63 }

 64 

 65 bool vis[maxn * maxn];

 66 

 67 int solve()

 68 {

 69     memset(vis, false, sizeof(vis));

 70     int ans = 1;

 71     for(int i = 0; i < n*n; i++) if(!vis[i])

 72     {

 73         int cnt = 0, j = i;

 74         do

 75         {

 76             vis[j] = 1;

 77             cnt++;

 78             j = cur[j];

 79         }while(j != i);

 80         ans = lcm(cnt, ans);

 81     }

 82     return ans;

 83 }

 84 

 85 int main()

 86 {

 87     //freopen("in.txt", "r", stdin);

 88 

 89     int T;

 90     scanf("%d", &T);

 91     for(int kase = 0; kase < T; kase++)

 92     {

 93         if(kase) puts("");

 94 

 95         scanf("%d", &n); getchar();

 96         string line, temp;

 97         getline(cin, line);

 98         stringstream ss(line);

 99         vector<string> op;

100         while(ss >> temp) op.push_back(temp);

101 

102         for(int i = 0; i < n*n; i++) cur[i] = i;

103         for(int i = op.size() - 1; i >= 0; i--) apply(op[i].c_str());

104         printf("%d\n", solve());

105     }

106 

107     return 0;

108 }
代码君

 

你可能感兴趣的:(shuffle)