首页 > 其他 > 详细

Codeforces 1294E - Obtain a Permutation

时间:2020-01-23 15:01:35      阅读:144      评论:0      收藏:0      [点我收藏+]

题目大意:

给定一个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

 1 /*
 2 Written By StelaYuri
 3 On 2020/01/23
 4 */
 5 #include<bits/stdc++.h>
 6 using namespace std;
 7 vector<int> v[200050];
 8 int cnt[200050];
 9 void solve(){
10     int n,m,i,j,d,ans=0,ansd;
11     cin>>n>>m;
12     for(i=0;i<n;i++)
13         for(j=0;j<m;j++){
14             cin>>d;
15             if((d-1)%m!=j||d>n*m)
16                 d=0;//标记必须进行更改值
17             v[j].emplace_back(d);
18         }
19     for(j=0;j<m;j++){
20         memset(cnt,0,n*sizeof(int));
21         for(i=0;i<n;i++)
22             if(v[j][i]){
23                 d=(v[j][i]-1)/m;
24                 cnt[(i+n-d)%n]++;//计算如果要移动到应该在的位置需要移动几步
25             }
26         ansd=0x3f3f3f3f;
27         for(i=0;i<n;i++)
28             ansd=min(ansd,i+n-cnt[i]);//寻找最优解
29         ans+=ansd;
30     }
31     cout<<ans<<\n;
32 }
33 int main(){
34     ios::sync_with_stdio(0);
35     cin.tie(0);cout.tie(0);
36     solve();
37     
38     return 0;
39 }

Codeforces 1294E - Obtain a Permutation

原文:https://www.cnblogs.com/stelayuri/p/12230624.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!