1. 程式人生 > >:七夕祭 (貨倉選址+均分紙牌)

:七夕祭 (貨倉選址+均分紙牌)

問題 : 七夕祭

時間限制: 1 Sec  記憶體限制: 128 MB

題目描述

七夕節因牛郎織女的傳說而被扣上了「情人節」的帽子。於是TYVJ今年舉辦了一次線下七夕祭。Vani同學今年成功邀請到了cl同學陪他來共度七夕,於是他們決定去TYVJ七夕祭遊玩。
TYVJ七夕祭和11區的夏祭的形式很像。矩形的祭典會場由N排M列共計N×M個攤點組成。雖然攤點種類繁多,不過cl只對其中的一部分攤點感興趣,比如章魚燒、蘋果糖、棉花糖、射的屋……什麼的。Vani預先聯絡了七夕祭的負責人zhq,希望能夠通過恰當地佈置會場,使得各行中cl感興趣的攤點數一樣多,並且各列中cl感興趣的攤點數也一樣多。不過zhq告訴Vani,攤點已經佈置完畢了,唯一的調整方式就是交換兩個相鄰的攤點。兩個攤點相鄰,當且僅當他們處在同一行或者同一列的相鄰位置上。由於zhq率領的TYVJ開發小組成功地扭曲了空間,每一行或每一列的第一個位置和最後一個位置也算作相鄰。現在Vani想知道他的兩個要求最多能滿足多少個。在此前提下,至少需要交換多少次攤點。

 

輸入

第一行包含三個整數N和M和T。T表示cl對多少個攤點感興趣。
接下來T行,每行兩個整數x,y,表示cl對處在第x行第y列的攤點感興趣。

 

輸出

首先輸出一個字串。如果能滿足 Vani 的全部兩個要求,輸出 both;如果通過調整 只能使得各行中 cl 感興趣的攤點數一樣多,輸出 row;如果只能使各列中 cl 感興趣的攤點 數一樣多,輸出 column;如果均不能滿足,輸出 impossible。
如果輸出的字串不是 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\n",solve(row,0)+solve(col,1));
39     }
40     else if(t % n == 0)
41     {
42         printf("row ");
43         printf("%lld\n",solve(row,0));
44     }
45     else if(t % m == 0)
46     {
47         printf("column ");
48         printf("%lld\n",solve(col,1));
49 
50     }
51     else printf("impossible\n");
52 }
View Code