Problem Description
输入一个n,接下来有n个数,让你求出能组成最多的对子或者顺子的和。
对子: (2,2),顺子: (1,2,3)。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6188
思路:
从小跑到大。例如1,1,2,3。跑到1的时候有对子,这时候优先要对子。不然你牺牲对子去换顺子,也就是一比一,根本不会赚。例如1,2,2,3。这个思路和前面一样,如果2,2拆开当顺子不会赚。例如1,2,3,3这时候跑1。发现1还有一张,2的个数是奇数,这时候就可以选择顺子1,2,3,因为3是最后面的。拆开它,一比一,不亏。它可能会和后面的5,6形成顺子,这时候就赚了。所以贪心的大体思路是这样,详细的看代码。
#include<cstdio>
#include<cstring>
using namespace std;
#define N 1000055
int vis[N];
int main()
{
int n, i, num;
while(~scanf("%d", &n))
{
memset(vis, 0, sizeof(vis));
for(i = 0; i < n; i++)
{
scanf("%d", &num);
vis[num]++;//这里我用的是下标存数,也就是桶
}
int ans = 0;
for(i = 1; i <= 1000000; i++)//从小跑到大
{
if(vis[i] >= 2)//第一个数如果有对子。那么优先对子
{
ans += vis[i] / 2;
vis[i] = vis[i] % 2;
}
if(i <= 999998)//如果第一个数是1,第二个数是奇数个,那么组成顺子
{
if(vis[i + 2] && vis[i] == 1 && vis[i + 1] % 2!=0 ) {
ans++;
vis[i]--; vis[i+1]--; vis[i+2]--;}
}
}
printf("%d\n", ans);//输出
}
}