题目大意:

给定一个n*m的矩阵

可以更改任意一个位置的值

也可以选择一整列全部往上移动一位,最上方的数移动到最下方

问最少操作多少次可以把这个矩阵移动成

1 2 3 ... m

m+1 m+2 m+3 ... 2m

...

(n-1)m+1 (n-1)m+2 (n-1)m+3 ... nm

解题思路:

如果一个数大于n*m,或者这个数不属于这一列((d-1)%m!=j)
那么这个数只能进行改变值的操作
存完后以列为单位分开求答案
用cnt[i]记录如果这一列移动k次的话,有多少数的值不需要进行更改
比如一列有10个元素,在向上移动5次后共有7个值回到了应该在的位置,那么此时n=10,cnt[5]=7
总共的操作次数为5+10-7=8次
由i+n-cnt[i]计算得来
所以在每次处理完cnt后遍历0到n-1求最优解,累加得出答案即可
在处理时,(v[j][i]-1)/m求出v[j][i]这个数原本应该在第几行
那么它的移动次数便是(i-d+n)%n
或者分开讨论
i>=d -> i-d
i<d -> i+n-d

#include<bits/stdc++.h>
using namespace std;
vector<int> v[];
int cnt[];
void solve(){
int n,m,i,j,d,ans=,ansd;
cin>>n>>m;
for(i=;i<n;i++)
for(j=;j<m;j++){
cin>>d;
if((d-)%m!=j||d>n*m)
d=;//标记必须进行更改值
v[j].emplace_back(d);
}
for(j=;j<m;j++){
memset(cnt,,n*sizeof(int));
for(i=;i<n;i++)
if(v[j][i]){
d=(v[j][i]-)/m;
cnt[(i+n-d)%n]++;//计算如果要移动到应该在的位置需要移动几步
}
ansd=0x3f3f3f3f;
for(i=;i<n;i++)
ansd=min(ansd,i+n-cnt[i]);//寻找最优解
ans+=ansd;
}
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio();
cin.tie();cout.tie();
solve(); return ;
}

最新文章

  1. ElasticSearch中bulkProcesser使用
  2. Linux时间同步
  3. 在一个SQL Server表中的多个列找出最大值
  4. css3新特性@media(媒体查询)
  5. The method setCharacterEncoding(String) is undefined for the type HttpServletResponse 是什么原因?
  6. websphere如何删除应用程序服务器(概要管理工具)
  7. docker 使用
  8. IntelliJ IDEA 开发工具项目maven管理
  9. WordPress mb.miniAudioPlayer插件多个跨站脚本漏洞
  10. jquery实现图片切换和js实现图片切换
  11. 2016年的个人计划-xiangjiejie
  12. spring来源理解-BeanFactory子类XmlBeanFactory创建过程
  13. CVSS3.0打分学习
  14. 基于Appium1.6.X的WebDriverAgent编译、安装
  15. FFMPEG结构体分析:AVPacket
  16. CentOS 7 安装 JAVA环境(JDK 1.8)
  17. Java开发笔记(五)数值变量的类型
  18. search 重要文件路径 搜索【原】
  19. 【PyQt5-Qt Designer】按钮系列
  20. hdu 5056 所有字母数都&lt;=k的子串数目

热门文章

  1. 启用sql日志
  2. ZOJ - 3870 Team Formation(异或)
  3. 安装与配置windbg的symbol(符号)
  4. BGP的地址聚合
  5. CSS 弹性盒子 flex的三个属性:grow、shrink、basis
  6. 基于磁盘的Kafka为什么这么快
  7. mysql时间类型总结及常用时间函数
  8. 剑指offer第40题
  9. bitcoind
  10. 微信小程序之组件常见的问题