标签:... cnt 10 更改 Codeforces 1294E 一列 Permutation 移动
题目大意:
给定一个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 }
标签:...,cnt,10,更改,Codeforces,1294E,一列,Permutation,移动 来源: https://www.cnblogs.com/stelayuri/p/12230624.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。