题意

现有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. 个人笔记-快速搭建k8s-1.16.0

    1.阿里云购买4台实例 4核16G 120G云盘 centos7.6 固定带宽1M(双主双从) https://www.aliyun.com/ 2.安装dockeryum remove docker ...

  2. Servlet 会话

    在网络的七层模型中,会话层位于传输层之上,它定义如何开始.控制和结束一个会话.七层模式目前仅仅处于理论阶段,但是Web中借鉴了其中的一些思路.在Web中浏览器第一次发送请求到服务器开始直到一方断开为止 ...

  3. C# 获取控制台程序路径

  4. 第二阶段:流程图:8.axure绘制简单业务流程图

    元件库选择流程图 流程图示例 一个简单的注册练习 线上可以写字 作业

  5. java xml的读取与写入(dom)

    首先,先获取到文档对象 private static Document getDocument(String path) { //1.创建DocumentBuilderFactory对象 Docume ...

  6. Dubbo的核心组件、架构设计与Dubbo面试考点

    1.Dubbo是什么? Dubbo 是一个分布式.高性能.透明化的 RPC 服务框架,提供服务自动注册.自动发现等高效服务治理方案, 可以和 Spring 框架无缝集成. RPC 指的是远程调用协议, ...

  7. jenkins安装自动部署

    1.1简介: 开源项目,一个可扩展的持续集成引擎.提供了一种易于使用的持续集成系统,能实施监控集成中存在的错误,提供详细的日志文件和提醒功能,还能用图表的形式形象地展示项目构建的趋势和稳定性.还做到持 ...

  8. 在nginx里面部署node.js本地服务器

    我一个前端,为啥要搞服务器呢?因为公司就招了一个后端啊,后端忙不过来,就叫我这个萌新前端去搞后端的东西,我太难了. 直接进入正题吧,因为公司需求,要我在nginx服务器上面搭一个node.js服务器, ...

  9. vue项目准备工作

    1.写文档: 产品说明.工作日志.接口说明文档.数据库说明文档.项目架构说明文档等···· 例如:后台管理系统:商品的管理.店铺的管理.店铺类别管理.管理员的管理.用户管理等·····    前端渲染 ...

  10. zabbix配置企业微信报警

    +++++++++++++++++++++++++++++++++++++++++ 1. 工作中最长使用的就是微信,普及,开源,而且免费!!! 2. 在企业微信中要记录的值: · 部门id · 企业i ...