题解 CF1399C Boats Competition

题意

给你 \(n\) 个数: \(w_1,w_2,\dots,w_n\) ,从中尽可能的选出 \(k\) 组,对于每一组 \((a_i,b_i)\) 满足 \(a_1+b_1 = a_2 + b_2 = \dots = a_k+b_k = s\) 。输出 \(k\)

分析

我们可以看到数据范围

\(n ( 1 \le n \le 50 )\) ,\(w_1, w_2, \dots, w_n(1 \le w_i \le n )\)

也就是说,\(s\) 最大为 \(100\) 。我们暴力枚举 \(s\) 然后找到答案就可以了。

代码

具体细节见注释。

// 头文件、快读快写自行脑补
#define re(x) read(x)
#define mes(x) memset(x,0,sizeof(x))

const int MAXN = 60;
int n,a[MAXN],tong[MAXN<<1];
// a : 原数组 , tong: 记录每个元素出现次数

int work(int x){
    int res = 0;
  // res : 当前情况下可以选的个数
  //为了防止重复计算,限定枚举范围为前一半,注意对于x为奇数的枚举范围(lim)。
    int lim = x/2;
    if(x &1) lim++;
    for(int i = 1;i < lim;i++)
	if(tong[i] && tong[x-i]) res += min(tong[i],tong[x-i]);
    if( x % 2 == 0) res += tong[x/2] / 2;
    return res;
}

int main (){
	int T;
	re(T);
	while(T--){
		re(n);
		mes(tong);
      //注意清空
		int ans = 0;
		for(int i = 1;i <= n;i++) re(a[i]),tong[a[i]]++;
      //枚举 s
		for(int i = 2;i <= 2*n;i++) ans = max(ans,work(i));
		write(ans);
	}
	return 0;
}
posted @ 2020-08-06 14:17  Werner_Yin  阅读(153)  评论(0编辑  收藏  举报