stick

木棍(stick)
Time Limit:1000ms Memory Limit:128MB

题目描述
LYK有很多木棍,具体的,总共有n根,且每根木棍都有一个长度。为了方便起见,我们可以用一个正整数ai表示第i根木棍的长度。
LYK有一把小刀,但这把小刀由于削木棍很不方便,对于一根木棍而言,它只能用这把小刀削掉恰好1的长度。
LYK觉得如果4根木棍头尾相连能恰好拼成长方形,说明这4根木棍是可以捆在一起卖钱的!具体的,如果这4根木棍的长度分别为a,b,c,d,如果满足a=b,c=d,说明恰好可以拼成长方形,且获得的钱为这4根木棍圈成的面积a*c。当然如果不能恰好拼成长方形,则卖不出去。
LYK想将这些木棍尽可能的4个一组捆在一起去卖钱,它想知道最多能获得多少钱。

输入格式(stick.in)
第一行一个数n,表示木棍的个数。
接下来一行n个数,第i个数ai表示第i根木棍的长度。

输出格式(stick.out)
一个数表示答案。

输入样例
12
2 3 3 4 5 5 5 5 7 9 11 13

输出样例
31

数据范围
对于30%的数据n=4。
对于50%的数据n<=20。
对于70%的数据n<=1000。
对于100%的数据1<=n<=100000,1<=ai<=1000000。

解法:
第一档前50%可能能用搜索来做(我一开始写了搜索但是不对啊)。
这个题可以用贪心来做(正解啦)。
对于同一长度的木棍,如果有奇数根(而且存在不是削下来的),就可以削掉一根,因为不削也没什么用处,削了或许有用。这样处理下来,最后一定是长的和长的搭配面积最大啦。
代码:

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cmath>
using namespace std;
int n,maxn;
long long ans;
int a[100009],b[1000009],c[1000009],cnt; 
int main()
{
    freopen("stick.in","r",stdin);
    freopen("stick.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
      scanf("%d",&a[i]),b[a[i]]++,c[a[i]]++,maxn=max(maxn,a[i]);

    for(int i=maxn;i>=1;i--) 
      if(b[i]%2==1&&c[i]>0) b[i]--,c[i]--,b[i-1]++;

    for(int i=maxn;i>=1;i--) 
      while(b[i]>=2) a[++cnt]=i,b[i]-=2;
    if(cnt%2) cnt--;
    for(int i=1;i<=cnt;i+=2)
      ans+=1ll*a[i]*a[i+1];
    printf("%lld",ans);
    return 0;   
}
/*
5
55 55 53 52 50
2860
*/
/*
5
55 55 51 59 20
0
*/
原文地址:https://www.cnblogs.com/dfsac/p/7587895.html