Codeforces 217div.2 C. Mittens

链接:http://codeforces.com/contest/370/problem/C

题意:有n双手袜(1<=n<=5000),每双袜子都有颜色ci(1<=c<=100),现在重新分配,问可否使每双袜子左右手颜色不同。若可以,输出一种方案;若不可以,求maximum,同样也输出一种maximum的方案。

输出格式:

第一行是n或maximum

以下每行有两个数表示手袜颜色,一个是左手的,一个是右手的 

 

思路:先求每种颜色有几双,设最大的是maxc双

若maxc>n/2,则不能令所有袜子所有手颜色不同。输出方案是,maxc的颜色选一个,其他颜色选一个,组成一双。注意一双手袜拆分成一个左手手袜,一个右手手袜,位置不一样。

最后剩余的是maxc颜色的袜子,直接输出。

若maxc<=n/2,则存在方案是每双手袜的颜色不一样。方案很多,只要保证每双手袜颜色都不同即可。

我的方法,先按颜色排序,然后首尾交换,遇到中间可能存在左右颜色一样的,就更前面已匹配的交换。

也可以先按颜色排序,然后将数组截成两份,两个数组匹配。手袜为奇数对时,有一双需要特殊处理。


ExpandedBlockStart.gif
 1 #include <iostream>
 2 #include <cstring>
 3  using  namespace std;
 4 
 5  const  int N =  5005;
 6  const  int M =  105;
 7 
 8  int main()
 9 {
10      int n, m, a[M], c, maxc, ans[ 2*N], indexa, finalAns[ 2*N];
11     cin >> n >> m;
12     memset(a,  0sizeof(a));
13     maxc =  0;
14      for( int i= 1; i<=n; i++)
15     {
16         cin >> c;
17         a[c] +=  2;
18          if(a[maxc]<a[c]) maxc = c;
19     }
20      if(a[maxc] > n)
21     {
22          int flag =  1;
23         cout << (n - a[maxc]/ 2)* 2 << endl;
24          for( int i= 1; i<=m; i++)
25         {
26              if(maxc==i)  continue;
27              while(a[i]> 0)
28             {
29                  if(flag% 2== 1)
30                     cout << maxc <<  "   " << i << endl;
31                  else
32                     cout << i <<  "   " << maxc << endl;
33                 flag++;
34                 a[i]--;
35             }
36         }
37          for( int i= 1; i<=n - (n - a[maxc]/ 2)* 2; i++)
38             cout << maxc <<  "   " << maxc << endl;
39     }
40      else
41     {
42         cout << n << endl;
43         indexa =  0;
44          for( int i= 1; i<=m; i++)
45         {
46              while(a[i]> 0)
47             {
48                 ans[++indexa] = i;
49                 a[i]--;
50             }
51         }
52          int flag =  1, indexfinal =  0;
53          int l =  1, r = indexa;
54          while(l<r)
55         {
56              if(flag% 2== 1)
57             {
58                 finalAns[l* 2- 2] = ans[l];
59                 finalAns[l* 2- 1] = ans[r];
60                  if(finalAns[l* 2- 2]==finalAns[l* 2- 1])
61                 {
62                     swap(finalAns[l* 2- 2],finalAns[indexfinal]);
63                     indexfinal +=  2;
64                 }
65                 l++; r--;
66             }
67              else
68             {
69                 finalAns[l* 2- 2] = ans[r];
70                 finalAns[l* 2- 1] = ans[l];
71                  if(finalAns[l* 2- 2]==finalAns[l* 2- 1])
72                 {
73                     swap(finalAns[l* 2- 2],finalAns[indexfinal]);
74                     indexfinal +=  2;
75                 }
76                 l++; r--;
77             }
78             flag++;
79         }
80          for( int i= 0; i<indexa/ 2; i++)
81             cout << finalAns[ 2*i] <<  "   " << finalAns[ 2*i+ 1] << endl;
82     }
83      return  0;
84 }
View Code 

 

 --------------------------------------

理解题意是王道。 

 

 

转载于:https://www.cnblogs.com/byluoluo/p/3463837.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值