问题连接
问题 :
现在给你n个整数,ai(1 <= i <= n)
我们定义了两个相同的数字(例如:2,2)一个Duizi,以及三个连续的正整数(例如:2,3,4)一个顺子。
现在你想用这些整数尽可能多地形成shunzi 和duizi。
尝试计算max(s)。
每个号码只能使用一次。
输入:
输入包含多个测试用例。
对于每个测试用例,第一行包含一个 n(1≤ n ≤1e6)。下一行包含n个整数ai(1≤ai≤n)
输出:
一个整数答案
Sample Input
7
1 2 3 4 5 6 7
9
1 1 1 2 2 2 3 3 3
6
2 2 3 3 3 3
6
1 2 3 3 4 5
Sample Output
2
4
3
2
Hint
Case 1(1,2,3)(4,5,6)
Case 2(1,2,3)(1,1)(2,2)(3,3)
Case 3(2,2)(3,3)(3,3)
Case 4(1,2,3)(3,4,5)
贪心思想:
用一个数组cnt统计每一个数字出现的次数,出现数字最多的情况也就是 1~n 每个数字出现一次。
for ( i in 1~n )
一 如果 1 和 2 出现过,优先考虑 1和2 对子的情况。。因为 1 和 2 至少和 3 形成 顺子,
假设 1 2 3 能组成对子 也能组成顺子 ,
根据贪心原则,一个顺子消耗三张牌,一个对子消耗两张牌,同样的权值,那么选择消耗小的。。
比如: 1 2 3 都 有两张,, 如果1 2 与 3 组成顺子,得 两分,消耗六张牌,
如果1 2 与 3 组成对子,得 两分,消耗四张牌,并且之后 3 还能继续得分
二 对于三之后的数字。
先考虑能否与它 之前 的两张牌组成 顺子,
再考虑 剩下的自己 组成对子。。
不需要考虑能否与后面的数字组成顺子,。
不好说明,仔细想想 可以理解。。。。。。。。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 1e6 + 10;
int t;
int cnta[MAXN];
int main()
{
std::ios::sync_with_stdio(false);
int n;
while(cin >> n)
{
memset(cnta,0,sizeof(cnta));
for(int i = 0; i < n;i++)
{
cin >> t;
cnta[t]++;
}
int ans = 0;
// n 张牌最多也就是1~n
for(int i = 1; i <= n; i++)
{
if((i == 1|| i == 2 )&& cnta[i] >= 2 )
{
ans += cnta[i]/2;
cnta[i] %= 2;
continue;
}
else
{
while(cnta[i] > 0 && cnta[i-1] > 0 && cnta[i-2] > 0)
{
ans++;
cnta[i]--;
cnta[i-1]--;
cnta[i-2]--;
}
if(cnta[i] >= 2)
{
ans += cnta[i]/2;
cnta[i] %= 2;
continue;
}
}
}
cout << ans << endl;
}
return 0;
}
。