105.七夕祭

在这里插入图片描述

题意:

有一个n*m的矩阵上面是n * m个摊位,给定T个cl感兴趣的摊位的坐标,问现在能否使每行或每列上cl感兴趣的摊位个数相等,可以交换相邻两个摊位的位置每行或每列的头和尾也属于相邻。

思路:

因为行列之间不能交换所以行列的判断是分开的,当总的感兴趣摊位数目不能均分到每一行或每一列时,则行的方案或列的方案不可行。单独看行和列的方案,如果可行那么每行上的感兴趣摊位数量等于总的感兴趣摊位数量/行数,是一个定值,那么我们可以遍历每一行如果当前行没有达到定值就去下一行拿(下一行可以被拿成负值,下一行可以去找再下一行拿,反正最终每行都是定值,就是要看怎么才能是最小交换次数这就需要用到中位数了)

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int H[maxn],Z[maxn],f[maxn];
ll cal(int a[],int n) {
	ll ans = 0;
	for(int i=1;i<=n;i++) {
		a[i] -= a[0]/n;
		f[i] = f[i-1]+a[i];
	}
	sort(f+1,f+1+n);
	for(int i=1;i<=n;i++) {
		ans+=abs(f[i]-f[(n+1)>>1]);
	}
	return ans;
}
int main() 
{
	int n,m,k;
	cin>>n>>m>>k;
	for(int i=1;i<=k;i++) {
		int x,y;
		cin>>x>>y;
		H[x]++;Z[y]++;
	}
	for(int i=1;i<=n;i++) {
		H[0] += H[i];
	}
	for(int i=1;i<=m;i++) {
		Z[0] += Z[i];
	}
	if(H[0]%n==0&&Z[0]%m==0) {
		printf("both %lld\n", cal(H, n) + cal(Z, m));
	} else if(H[0]%n == 0) {
		printf("row %lld\n", cal(H, n) );
	} else if(Z[0]%m == 0) {
		printf("column %lld\n",  cal(Z, m));
	} else {
		cout<<"impossible"<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值