题意

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


思考

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

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

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

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

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


代码

 #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn=1E2+;
int X[maxn*maxn],Y[maxn*maxn];
int a[maxn][maxn],n,m,wait[maxn];
ull seed=;
inline int R(int l,int r)
{
seed^=seed<<;
seed^=seed>>;
seed^=;
return seed%(r-l+)+l;
}
struct note
{
int opt,x,y;
note(int a=,int b=,int c=)
{
opt=a,x=b,y=c;
}
};
vector<note>ans;
inline void swap(int x1,int y1,int x2,int y2,int x3,int y3)
{
swap(X[a[x1][y1]],X[a[x3][y3]]);
swap(Y[a[x1][y1]],Y[a[x3][y3]]);
swap(X[a[x1][y1]],X[a[x2][y2]]);
swap(Y[a[x1][y1]],Y[a[x2][y2]]);
swap(a[x1][y1],a[x3][y3]);
swap(a[x3][y3],a[x2][y2]);
int len1=y2-y1,len2=x2-x3;
if(len1<)
len1+=m;
if(len2<)
len2+=n;
ans.push_back(note(,x1,len1));
ans.push_back(note(,y2,len2));
ans.push_back(note(,x1,m-len1));
ans.push_back(note(,y2,n-len2));
}
inline void swapRow(int x,int y1,int y2,int y3)
{
swap(x,y1,x,y2,x-,y2);
swap(x,y1,x,y2,x-,y2);
swap(x,y3,x,y2,x-,y2);
}
void out()
{
for(int i=;i<=n;++i,cout<<endl)
for(int j=;j<=m;++j)
{
cout.width();
cout<<a[i][j];
}
}
void work()
{
for(int i=;i<=n-;++i)
{
for(int j=;j<=m;++j)
{
int num=(i-)*m+j-;
if(a[i][j]==num)
continue;
if(i==X[num])
swap(X[num],Y[num],i,j,i+,j);
else if(j==Y[num])
swap(X[num],j==?m:,X[num],Y[num],i,j);
else
{
int x=X[num],y=Y[num];
swap(x,y,x,j,i,j);
swap(x,y,x,j,i,j);
}
}
}
for(int i=;i<=m-;++i)
{
int num=(n-)*m+i-;
if(a[n][i]==num)
continue;
if(Y[num]==i+)
swapRow(n,i,i+,i+);
else
{
int G=Y[num];
swapRow(n,i,i+,G);
swapRow(n,i,i+,G);
}
}
}
void row(int x,int y)
{
ans.push_back(note(,x,y));
for(int i=;i<=m;++i)
wait[i]=a[x][i-y>=?i-y:i-y+m];
for(int i=;i<=m;++i)
a[x][i]=wait[i],Y[wait[i]]=i;
}
void col(int x,int y)
{
ans.push_back(note(,x,y));
for(int i=;i<=n;++i)
wait[i]=a[i-y>=?i-y:i-y+n][x];
for(int i=;i<=n;++i)
a[i][x]=wait[i],X[wait[i]]=i;
}
bool check()
{
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
if(a[i][j]!=(i-)*m+j-)
return false;
return true;
}
int main()
{
srand(time());
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
{
cin>>a[i][j];
X[a[i][j]]=i,Y[a[i][j]]=j;
}
int T=;
while(T--)
{
work();
if(check())
break;
int t=;
row(n,);
}
if(!check())
{
cout<<-<<endl;
return ;
}
cout<<ans.size()<<endl;
for(int i=;i<ans.size();++i)
cout<<ans[i].opt<<" "<<ans[i].x<<" "<<ans[i].y<<endl;
return ;
}

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

19_07_08校内训练[grid]的更多相关文章

  1. [4.14校内训练赛by hzwer]

    来自FallDream的博客,未经允许,请勿转载,谢谢. hzwer又出丧题虐人 4道noi....        很奇怪 每次黄学长出题总有一题我做过了. 嗯题目你们自己看看呗 好难解释 ----- ...

  2. [2017.4.7校内训练赛by hzwer]

    来自FallDream的博客,未经允许,请勿转载,谢谢. 报警啦.......hzwer又出丧题虐人啦..... 4道ctsc...有一道前几天做过了,一道傻逼哈希还wa了十几次,勉强过了3题..我好 ...

  3. [3.24校内训练赛by hzwer]

    来自FallDream的博客,未经允许,请勿转载,谢谢. ----------------------------------------------------------------------- ...

  4. 19_04_19校内训练[Game]

    题意 给出n,等概率地生成一个1~n的数列.现在有n个人从左到右站成一排,每个人拿有当前数列位置上的数字,并且一开始都不知道数字是多少(但知道n是多少).从左到右让每个人进行如下选择: 1.选择保留自 ...

  5. 19_04_02校内训练[deadline]

    题意 给出一个二分图,左边为A集合,右边为B集合,要求把A集合中每一个点染为黑白两色中的一种,B集合中的颜色已定.染色后对于原本相邻且颜色相同的点,建立新的二分图,即得到了两个新的二分图,它们是独立的 ...

  6. 平面图转对偶图&19_03_21校内训练 [Everfeel]

    对于每个平面图,都有唯一一个对偶图与之对应.若G‘是平面图G的对偶图,则满足: G'中每一条边的两个节点对应着G中有公共边的面,包括最外部无限大的面. 直观地讲,红色标出来的图就是蓝色标出的图的对偶图 ...

  7. fzyzojP3979 -- [校内训练20180914]魔法方阵

    原题见CF632F https://blog.csdn.net/Steaunk/article/details/80217764 这个比较神仙了 点边转化, 把max硬生生转化成了路径最大值,再考虑所 ...

  8. fzyzojP3580 -- [校内训练-互测20180315]小基的高智商测试

    题目还有一个条件是,x>y的y只会出现一次(每个数直接大于它的只有一个) n<=5000 是[HNOI2015]实验比较 的加强版 g(i,j,k)其实可以递推:g(i,j,k)=g(i- ...

  9. fzyzojP3372 -- [校内训练20171124]博弈问题

    对于每个点都要答案 还是异或 trie树合并石锤了 朴素枚举是O(n^2*17)的 怎么办呢? 我们发现合并的时候,一些部分的trie的子树还是不变的 改变的部分也就是合并的复杂度可以接受 鉴于大部分 ...

随机推荐

  1. IdentityServer4 sign-in

    原文地址 Sign-in IdentityServer 代表 user 分配token之前,user必须登录IdentityServer Cookie authentication 使用 cookie ...

  2. Vue.js provide / inject 踩坑

    最近学习JavaScript,并且使用vuejs,第一次使用依赖注入,结果踩坑,差点把屏幕摔了..始终获取不到如组件的属性,provide中的this对象始终是子组件的this对象 慢慢也摸索到了些v ...

  3. 关于python2和python3除法的区别

    在Python2中,除法的取值结果取整数 >>> 9/2 4 而在Python3中,除法/的结果包含小数,如果只想取整数需要使用// >>> 9/2 4.5 > ...

  4. HashMap、lru、散列表

    HashMap HashMap的数据结构:HashMap实际上是一个数组和链表("链表散列")的数据结构.底层就是一个数组结构,数组中的每一项又是一个链表. hashCode是一个 ...

  5. 使用vue 对二进制文件 实现下载(blob对象

    有很多网站会涉及到文件下载,这里我们使用axios 发送请求 接受数据 第一步 模仿jQ 封装接口 Vue.prototype.$xlsx_post = function (url, data, fu ...

  6. 基础之Lamada和Stream的邂逅

    show me the code and take to me,做的出来更要说的明白 GitHub项目JavaHouse同步收录 喜欢就点个赞呗! 你的支持是我分享的动力! 引入 是否有遇到看不懂身边 ...

  7. $51nod\ 1522$ 上下序列 $dp$

    正解:$dp$ 解题报告: 传送门$QwQ$ 一年过去了$gql$还是不咋会这题,,,好菜昂我的$NOIp$必将惨败了$kk$ 考虑从大到小枚举两个相同的数填哪儿,根据那个限制,十分显然的是这两个数必 ...

  8. React Hooks 完全指南,读React作者博文感悟(2W字精华)

    阅读 facebook大佬:Dan Abramov 的文章颇有感悟 大佬 github地址 https://github.com/gaearon 重点总结 useEffect 是同步的 状态是捕获的当 ...

  9. 21.pyinstaller相关参数

    pyinstaller相关参数                  命令                                                          描述  -F, ...

  10. PS/2的相关知识

    PS/2接口 很多微机上采用PS/2口来连接鼠标和键盘.PS/2接口与传统的键盘接口除了在接口外型.引脚有不同外,在数据传送格式上是相同的.现在很多主板用PS/2接口插座连接键盘,传统接口的键盘可以通 ...