算法进阶指南[七夕祭]

2021/7/4 20:21:41

本文主要是介绍算法进阶指南[七夕祭],对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!


会场由N*M个摊点组成

* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *

要使每一行感兴趣的摊点一样多,只能调整相邻两个点(同行或者同列)

点的总和位为T
如果T不能整除N,则不能通过row达到
如果T不能整除M,则不能通过column达到

由于左右调整和上下调整不改变行/列的个数,

因此我们讨论如何通过左右调整使得每一列的数量相等;

1.记录每一列的数量并记录前缀和
如果X可以整除先考虑某一列,每一列最终的个数将是T/M个
因此对于第C[i]个点将要调整|C[i]-T/M|次


2.准确来说,从第一个点开始,一共需要调整∑(1,m)|i*T/M-G[i]| (G[i]为前缀和)
相当于我们取A[i]=C[i]-T/M,S[i]=∑A[i]


3.而如果把它当作一个环来处理,就是选取第k个位置断开,每个位置的变化:
i+k<=M:
A[k+i]->S[k+1]-S[k]
i<k:
A[i]->S[i]+S[M]-S[k]
因此最后的总和是∑|S[i]-S[k]|


这个便是仓库选址这一道题目的中位数思想:(看不懂的先做一下这道题目铺垫一下)
https://www.acwing.com/problem/content/106/

AC 代码:

#include<bits/stdc++.h>
#define MAXN 100010
using namespace std;

int n,m,t,x,y;
long long res_row,res_column; 
int row[MAXN]={0},column[MAXN]={0},r[MAXN],c[MAXN];

int main(){
    scanf("%d%d%d",&n,&m,&t);
    for(int i=1;i<=t;i++){
        scanf("%d%d",&x,&y);
        row[x]++,column[y]++;
    }
    if(t%n==0||t%m==0){
        if(t%m==0&&t%n!=0){
            printf("column ");
            //处理前缀和
            for(int i=1;i<=m;i++){
                c[i]=c[i-1]+column[i]-t/m;
            }
            //排序,计算∑|S[i]-S[k]|
            sort(c+1,c+1+m);int u=c[(m+1)/2];
            for(int i=1;i<=m;i++) res_column+=abs(c[i]-u);
            printf("%lld",res_column);
        }
        else if(t%n==0&&t%m!=0){
            printf("row ");
            for(int i=1;i<=n;i++){
                r[i]=r[i-1]+row[i]-t/n;
            }
            sort(r+1,r+1+n);
            int u=r[(n+1)/2];
            for(int i=1;i<=n;i++) res_row+=abs(r[i]-u);
            printf("%lld",res_row);
        }
        else{
            printf("both ");
            //列
            for(int i=1;i<=m;i++){
                c[i]=c[i-1]+column[i]-t/m;
            }
            //排序,计算∑|S[i]-S[k]|
            sort(c+1,c+1+m);
            int u=c[(m+1)/2];
            for(int i=1;i<=m;i++) res_column+=abs(c[i]-u);
            //行
            for(int i=1;i<=n;i++){
                r[i]=r[i-1]+row[i]-t/n;
            }
            sort(r+1,r+1+n);
            u=r[(n+1)/2];
            for(int i=1;i<=n;i++) res_row+=abs(r[i]-u);
            printf("%lld",res_row+res_column);
        }
        
    }
    else printf("impossible\n");
    return 0;
}

 



这篇关于算法进阶指南[七夕祭]的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程