2018TYUT暑期ACM模拟赛(1)
Duizi and Shunzi HDU - 6188
题意:能出的最多的对子或者顺子形式的和。
思路:贪心法,一开始自己的思路是错误的。错误想法:先找出对子为先,后再在考虑,能否把某个对子拆成两个顺子。这样就有一个样例是过不去的如:1 2 3 3 4 5 5 6 7。用我的想法答案是2.而实际上是可以3的。123 345 567 我想法的漏洞在,只考虑拆掉一个对子,而这个例子或者更多例子需要我拆很多对子。所以我这样想是行不通的。
然后谈论,正确思路:正确的贪心。先从小到大开始过一遍,优先组合对子,然后剩下的看能否和后面的两个组成顺子。判断条件:i,i+1为奇数,i+2存在。(其实队i+1要是为奇数这里还是有点疑惑)
ps:别的大佬博客里的思路:从小跑到大。例如1,1,2,3。跑到1的时候有对子,这时候优先要对子。不然你牺牲对子去换顺子,也就是一比一,根本不会赚。例如1,2,2,3。这个思路和前面一样,如果2,2拆开当顺子不会赚。例如1,2,3,3这时候跑1。发现1还有一张,2的个数是奇数,这时候就可以选择顺子1,2,3,因为3是最后面的。拆开它,一比一,不亏。它可能会和后面的5,6形成顺子,这时候就赚了。所以贪心的大体思路是这样,详细的看代码。
ps:鱼菜菜要坚强。 -_- 。
AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e6+100;
int card[maxn];
int dp[maxn];
int main()
{
int n,a;//1-1e6,1-n
while(cin>>n){
int cnt=0;
int vis=0;
memset(card,0,sizeof(card));
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
cin>>a;
card[a]++;
}
for(int i=1;i<=n;i++)
{
cnt+=card[i]/2;
card[i]%=2;
if(card[i]&&card[i+1]%2&&card[i+2]&&i+1<=n)
{
card[i]--;
card[i+1]--;
card[i+2]--;
cnt++;
}
}
cout<<cnt<<endl;
}
return 0;
}