zoukankan      html  css  js  c++  java
  • 19_07_08校内训练[grid]

    题意

    现有n*m的长方形网格,每个格子中写着一个数,并构成了[0,n*m)的排列。每次可以将一行循环平移x格,也可以将一列循环平移x格。给出初始状态,给出一个到达给定状态的方案。n*m<=10000,n,m>=2。


    思考

    发现存在一种方法,能够使任意三个方格进行顺时针或逆时针改变位置。其中有一个方格的行和列由剩余两个方格决定。

    这样一来,我们可以将前n-1行排成有序的,只剩下最后一行是无序的。

    通过第一张改变位置的方式,我们也可以将同一行的任意三个方格进行循环平移。这样可以将最后一行的前m-2个排成有序的,剩下的两个不一定有序。

    这种方法虽然不能判断出是否能够达到有序状态,但是在随机情况下会以一定概率达到。因此可以重复打乱原始序列,进行多次判断。

    总复杂度O(Tnm),T为随机次数。


    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef unsigned long long ull;
      4 const int maxn=1E2+5;
      5 int X[maxn*maxn],Y[maxn*maxn];
      6 int a[maxn][maxn],n,m,wait[maxn];
      7 ull seed=233;
      8 inline int R(int l,int r)
      9 {
     10     seed^=seed<<13;
     11     seed^=seed>>7;
     12     seed^=1;
     13     return seed%(r-l+1)+l;
     14 }
     15 struct note
     16 {
     17     int opt,x,y;
     18     note(int a=0,int b=0,int c=0)
     19     {
     20         opt=a,x=b,y=c;
     21     }
     22 };
     23 vector<note>ans;
     24 inline void swap(int x1,int y1,int x2,int y2,int x3,int y3)
     25 {
     26     swap(X[a[x1][y1]],X[a[x3][y3]]);
     27     swap(Y[a[x1][y1]],Y[a[x3][y3]]);
     28     swap(X[a[x1][y1]],X[a[x2][y2]]);
     29     swap(Y[a[x1][y1]],Y[a[x2][y2]]);
     30     swap(a[x1][y1],a[x3][y3]);
     31     swap(a[x3][y3],a[x2][y2]);
     32     int len1=y2-y1,len2=x2-x3;
     33     if(len1<0)
     34         len1+=m;
     35     if(len2<0)
     36         len2+=n;
     37     ans.push_back(note(1,x1,len1));
     38     ans.push_back(note(2,y2,len2));
     39     ans.push_back(note(1,x1,m-len1));
     40     ans.push_back(note(2,y2,n-len2));
     41 }
     42 inline void swapRow(int x,int y1,int y2,int y3)
     43 {
     44     swap(x,y1,x,y2,x-1,y2);
     45     swap(x,y1,x,y2,x-1,y2);
     46     swap(x,y3,x,y2,x-1,y2);
     47 }
     48 void out()
     49 {
     50     for(int i=1;i<=n;++i,cout<<endl)
     51         for(int j=1;j<=m;++j)
     52         {
     53             cout.width(4);
     54             cout<<a[i][j];
     55         }
     56 }
     57 void work()
     58 {
     59     for(int i=1;i<=n-1;++i)
     60     {
     61         for(int j=1;j<=m;++j)
     62         {
     63             int num=(i-1)*m+j-1;
     64             if(a[i][j]==num)
     65                 continue;
     66             if(i==X[num])
     67                 swap(X[num],Y[num],i,j,i+1,j);
     68             else if(j==Y[num])
     69                 swap(X[num],j==1?m:1,X[num],Y[num],i,j);
     70             else
     71             {
     72                 int x=X[num],y=Y[num];
     73                 swap(x,y,x,j,i,j);
     74                 swap(x,y,x,j,i,j);
     75             }
     76         }
     77     }
     78     for(int i=1;i<=m-2;++i)
     79     {
     80         int num=(n-1)*m+i-1;
     81         if(a[n][i]==num)
     82             continue;
     83         if(Y[num]==i+1)
     84             swapRow(n,i,i+1,i+2);
     85         else
     86         {
     87             int G=Y[num];
     88             swapRow(n,i,i+1,G);
     89             swapRow(n,i,i+1,G);
     90         }
     91     }
     92 }
     93 void row(int x,int y)
     94 {
     95     ans.push_back(note(1,x,y));
     96     for(int i=1;i<=m;++i)
     97         wait[i]=a[x][i-y>=1?i-y:i-y+m];
     98     for(int i=1;i<=m;++i)
     99         a[x][i]=wait[i],Y[wait[i]]=i;
    100 }
    101 void col(int x,int y)
    102 {
    103     ans.push_back(note(2,x,y));
    104     for(int i=1;i<=n;++i)
    105         wait[i]=a[i-y>=1?i-y:i-y+n][x];
    106     for(int i=1;i<=n;++i)
    107         a[i][x]=wait[i],X[wait[i]]=i;
    108 }
    109 bool check()
    110 {
    111     for(int i=1;i<=n;++i)
    112         for(int j=1;j<=m;++j)
    113             if(a[i][j]!=(i-1)*m+j-1)
    114                 return false;
    115     return true;
    116 }
    117 int main()
    118 {
    119     srand(time(0));
    120     ios::sync_with_stdio(false);
    121     cin>>n>>m;
    122     for(int i=1;i<=n;++i)
    123         for(int j=1;j<=m;++j)
    124         {
    125             cin>>a[i][j];
    126             X[a[i][j]]=i,Y[a[i][j]]=j;
    127         }
    128     int T=10;
    129     while(T--)
    130     {
    131         work();
    132         if(check())
    133             break;
    134         int t=10;
    135         row(n,1);
    136     }
    137     if(!check())
    138     {
    139         cout<<-1<<endl;
    140         return 0;
    141     }
    142     cout<<ans.size()<<endl;
    143     for(int i=0;i<ans.size();++i)
    144         cout<<ans[i].opt<<" "<<ans[i].x<<" "<<ans[i].y<<endl;
    145     return 0;
    146 }
    View Code

     NOTE:最好要多随机几行和几列,防止极端数据。

  • 相关阅读:
    json和xml数据的解析
    block(闭包)
    自定义控件注意点
    字符串使用
    如何用运行时,给系统分类添加属性?
    论代码规范
    常用设计模式
    多控制器管理
    GDI+学习及代码总结之-----画笔 .
    MFC程序添加Web浏览器控件(IE控件)
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/11152115.html
Copyright © 2011-2022 走看看