zoukankan      html  css  js  c++  java
  • 思维——cf1294E

    一开始以为是个模式匹配题,其实要先推出性质,就很好做了

    /*
    由于每列都具有独立性,所以一列一列计算答案
    问题转化成给定一个数组a,要对其进行最小次数的循环上移或修改,最后匹配数组b 
        观察b数组的性质,我们发现第j列的数组b[j][] = {j+(i-1)m},为了方便处理,我们把第j列的a,b数组统统-j+m
        处理后的b[j][i]=im,我们只要考虑a数组里是m倍数的数即可,剩下的数不管怎么移动永远配不上 
        我们再来考虑剩下的数,考虑a[i]=km
            k==i,那么a[i]属于不用移动就能配上
            k<i,那么a[i]上移i-k能配上
            k>i,那么a[i]上移i+n-k能配上
        开个桶cnt[i]来记录上移i格配上的数字个数,找到消耗最小的上移策略即可 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 200005
    
    vector<int>tmp[N],a[N];
    int sum,n,m;
    
    int cnt[N];
    int solve(int col,vector<int>a){
        int res=0; 
        cnt[0]=0;
        for(int i=1;i<=n;i++)a[i]+=-col+m,cnt[i]=0;//初始化 
        for(int i=1;i<=n;i++){
            if(a[i]%m!=0 || a[i]/m>n)res++;
            else {
                int k=a[i]/m;
                if(k==i)cnt[0]++;
                else if(k<i)cnt[i-k]++;
                else cnt[i+n-k]++;
            }
        }
        int Min=0x3f3f3f3f,base=n-res;
        for(int i=0;i<=n;i++)
            Min=min(Min,i+base-cnt[i]);
        return Min+res;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            tmp[i].push_back(0);
            for(int j=1;j<=m;j++){
                int x;scanf("%d",&x);
                tmp[i].push_back(x); 
            }
        }
        for(int j=1;j<=m;j++){
            a[j].push_back(0);
            for(int i=1;i<=n;i++)
                a[j].push_back(tmp[i][j]);
        } 
        
        for(int j=1;j<=m;j++)
            sum+=solve(j,a[j]);
            
        cout<<sum<<'
    ';
    } 
  • 相关阅读:
    如何写一个完整课堂管理系统(数据库增删改查)
    关于java异常处理的思考
    java03类与对象相关问题
    java02实验:方法
    java02动手动脑
    java课堂动手动脑及课后实验总结
    java测试银行系统源代码
    JAVA程序系统测试感受
    2018年第八周暑假进度报告
    2018第七周进度总结报告
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12260106.html
Copyright © 2011-2022 走看看