码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-03-13 00:13:04      阅读:319      评论:0      收藏:0      [点我收藏+]

标签:

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

用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 }
代码君

 

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

标签:

原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/4333952.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!