题意

现有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. 开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor

    在今年年初, 恰逢新春佳节临近的时候. 微软给全球的C#开发者们, 着实的送上了一分惊喜. 微软正式开源Blazor ,将.NET带回到浏览器. 这个小惊喜, 迅速的在dotnet开发者中间传开了. ...

  2. 初识Contiv

    Contiv是一个用于跨虚拟机.裸机.公有云或私有云的异构容器部署的开源容器网络架构.作为业界最强大的容器网络架构,Contiv具有2层.3层.overlay和ACI模式,能够与思科基础设施进行本地集 ...

  3. Channel 9视频整理【3】

    Will 保哥 微软mvp https://channel9.msdn.com/Niners/Will_Huang 繁体中文视频 Visual Studio 2017 新功能探索 https://ch ...

  4. boostrap-非常好用但是容易让人忽略的地方【4】:Font Awesome

    font-awesome基本用法 官方代码传送门 font-awesome在bootstrap中的特殊用法(这个才是重点) 要点归纳1(官方) 官方代码传送门 要点归纳2(我的) <a href ...

  5. 关于本地用svn up的时候报cannot update svn folder: "unversioned directory of the same name already exists

    这是因为本地有手动添加过一个文件夹,然后和svn上的同名文件夹重名了,所以无法从svn update下来 解决办法如下: 1.先给本地的重名文件夹改名 mv  dirname repeatdirnam ...

  6. python3.6中使用selenium + chromedriver访问Chrome浏览器时报错

    from selenium import webdriver from selenium.webdriver.chrome.options import Options if __name__ == ...

  7. Kafka 集群在马蜂窝大数据平台的优化与应用扩展

    马蜂窝技术原创文章,更多干货请订阅公众号:mfwtech Kafka 是当下热门的消息队列中间件,它可以实时地处理海量数据,具备高吞吐.低延时等特性及可靠的消息异步传递机制,可以很好地解决不同系统间数 ...

  8. 洛谷$P2153\ [SDOI2009]$ 晨跑 网络流

    正解:网络流 解题报告: 传送门$QwQ$ 题目好长昂,,,大概概括下$QwQ$.就说有$n$个节点$m$条边,然后要求每次走的路径都不一样,问最多能走多少次,然后在次数最多的前提下问路径最短是多少$ ...

  9. ng-zorro-antd中踩过的坑

    ng-zorro-antd中踩过的坑 前端项目中,我们经常会使用阿里开源的组件库:ant-design,其提供的组件已经足以满足多数的需求,拿来就能直接用,十分方便,当然了,有些公司会对组件库进行二次 ...

  10. 2020面试还搞不懂MyBatis?快看看这27道面试题!(含答案和思维导图)

    前言 MyBatis是一个优秀的持久层ORM框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL 本身,而不需要花费精力去处理例如注册驱动.创建connection.创建statem ...