:七夕祭 (货仓选址+均分纸牌)
Posted iwannabe
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了:七夕祭 (货仓选址+均分纸牌)相关的知识,希望对你有一定的参考价值。
问题 : 七夕祭
时间限制: 1 Sec 内存限制: 128 MB题目描述
TYVJ七夕祭和11区的夏祭的形式很像。矩形的祭典会场由N排M列共计N×M个摊点组成。虽然摊点种类繁多,不过cl只对其中的一部分摊点感兴趣,比如章鱼烧、苹果糖、棉花糖、射的屋……什么的。Vani预先联系了七夕祭的负责人zhq,希望能够通过恰当地布置会场,使得各行中cl感兴趣的摊点数一样多,并且各列中cl感兴趣的摊点数也一样多。不过zhq告诉Vani,摊点已经布置完毕了,唯一的调整方式就是交换两个相邻的摊点。两个摊点相邻,当且仅当他们处在同一行或者同一列的相邻位置上。由于zhq率领的TYVJ开发小组成功地扭曲了空间,每一行或每一列的第一个位置和最后一个位置也算作相邻。现在Vani想知道他的两个要求最多能满足多少个。在此前提下,至少需要交换多少次摊点。
输入
接下来T行,每行两个整数x,y,表示cl对处在第x行第y列的摊点感兴趣。
输出
如果输出的字符串不是 impossible, 接下来输出最小交换次数,与字符串之间用一 个空格隔开。
样例输入
2 3 4
1 3
2 1
2 2
2 3
样例输出
row 1
提示
对于30%的数据,N,M≤100。
对于70%的数据,N,M≤1000。
对于100%的数据,1≤N,M≤100000,0≤T≤min(NM,100000),1≤x≤N,1≤y≤M。
题意:通过最小的次数交换,使得每行每列上cl感兴趣的摊点数相同。
思路:因为摊点进行行交互并不影响列上的情况,进行列交换也不影响行上的情况,所以我们可以分别进行 -------- 1、行交换 2、列交换
① 我们很容易知道如果要进行行交换(列),t%n(m) == 0,否则是无法平均分配的
②如果首尾不相连(无法交换),我们知道这是一个均分纸牌问题 ans = sum(| i*(t/n)- G【i】 |)(G【i】是牌数C【i】的前缀和),可以理解为当前拥有G【i】张牌,规定拥有i*(t/n)张,当前需要移动次数就是| i*(t/n)-G【i】|,令A【i】 = C【i】-t/n,S【i】为A【i】的前缀和,ans = |S【i】|
③如果首尾相连(可以交换),那就变成了一个环形的均分纸牌,但是我们可以知道,最有的方案肯定存在一个相邻的位置没有进行交换,将其拆开,分成一条链,又变成了均分纸牌问题
(假设 n 个位置,总共n-1对相邻关系,如果进行了n-2次交换,使得n-1个位置平衡,那么第n个位置也肯定平衡了,就不必交换)
④那么我们需要枚举拆开的位置 j, ans += S【j+i】-S【j】 (j+i <= n)
ans+= S【n】+S【j+i-n】-S【j】 ( i + j > n)
因为S【n】是前面所有A【i】的前缀和,S【n】 == 0 (S【n】 == G【n】- t)
所以ans = sum( | S【i】-S【k】|),这就是一个货仓选址问题
⑤我们将 S 排序,知道如果
n为奇数,ans = sum(| S【i】- S【(n+1)/2】|)
n为偶数,ans = sum(| S【i】- S【n/2】|)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,t; 4 typedef long long ll; 5 const int maxn = 1e5+5; 6 ll row[maxn]; 7 ll col[maxn]; 8 9 int solve(ll *Ar,int type) 10 { 11 int len,avr; 12 if(type == 0)len = n,avr = t/n; 13 else len = m,avr = t/m; 14 for(int i=1;i<=len;i++)Ar[i] += Ar[i-1]-avr; 15 ll ans = 0; 16 sort(Ar+1,Ar+1+len); 17 int tmp; 18 if(len & 1)tmp = Ar[(len+1)/2]; 19 else tmp = Ar[(len/2)]; 20 for(int i=1;i<=len;i++)ans += abs(Ar[i]-tmp); 21 return ans; 22 } 23 24 int main() 25 { 26 scanf("%d%d%d",&n,&m,&t); 27 for(int i=1;i<=t;i++) 28 { 29 int x,y; 30 scanf("%d%d",&x,&y); 31 row[x]++; 32 col[y]++; 33 } 34 35 if(t%n == 0 && t% m == 0) 36 { 37 printf("both "); 38 printf("%lld ",solve(row,0)+solve(col,1)); 39 } 40 else if(t % n == 0) 41 { 42 printf("row "); 43 printf("%lld ",solve(row,0)); 44 } 45 else if(t % m == 0) 46 { 47 printf("column "); 48 printf("%lld ",solve(col,1)); 49 50 } 51 else printf("impossible "); 52 }
以上是关于:七夕祭 (货仓选址+均分纸牌)的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj3032][TYVJ P1924]七夕祭(环形均分纸牌,货仓选址)