2017广西邀请赛Duizi and Shunzi(贪心+DP)

xiaoxiao2021-02-28  121

题意:给你n个数,问你最多能组成多少顺子和对子

题解:和bzoj上的一道题类似,不过bzoj上对子是3张牌,所以无脑先选对子即可,然而这道题对子是

两张牌,因此之前的贪心还是有些问题的,比如: 1 2 3 3 4 5 ,答案应该是2,。

但是我们仍然可以考虑先选对子,然后让每种牌最多留下一个对子(可以自己证明,留的多了没用)

然后我们判断留下的对子能否组成两个顺子即可,当然遍历的过程中顺子也都找出来了。。

#include<set> #include<map> #include<stack> #include<queue> #include<vector> #include<string> #include<math.h> #include<stdio.h> #include<iostream> #include<string.h> #include<stdlib.h> #include<algorithm> #include<functional> using namespace std; typedef long long ll; #define inf 1000000000 #define mod 1000000007 #define maxn 2600005 #define PI acos(-1.0) #define lowbit(x) (x&-x) #define eps 1e-9 int a[maxn], b[maxn], dp[maxn]; int main(void) { int n, i, j, k, ans; while (scanf("%d", &n) != EOF) { ans = 0; memset(b, 0, sizeof(b)); memset(dp, 0, sizeof(dp)); for (i = 1;i <= n;i++) scanf("%d", &a[i]), b[a[i]]++; for (i = 1;i <= n;i++) { if (b[i] <= 2) continue; ans += b[i] / 2; if (b[i] % 2 == 0) ans--; b[i] = 2 - (b[i] % 2 == 1); } dp[1] = b[1] / 2; if (b[1] > 1) b[1] = 0; dp[2] = dp[1] + b[2] / 2; if (b[2] > 1) b[2] = 0; for (i = 3;i <= n;i++) { dp[i] = dp[i - 1]; if (b[i] == 0) continue; if (b[i] > 1) dp[i] = dp[i - 1] + 1; if (b[i - 1] && b[i - 2] && dp[i] <= dp[i - 2] + 1) dp[i] = dp[i - 2] + 1, b[i]--, b[i - 1]--, b[i - 2]--; else if (b[i - 1] && b[i - 2] && dp[i] > dp[i - 2] + 1 || b[i - 1] == 0 || b[i - 2] == 0) { if (b[i] > 1) b[i] = 0; } //printf("%d %d\n", dp[i], i); } printf("%d\n", ans + dp[n]); } return -1; } /* 10 1 1 1 2 3 4 5 6 7 8 9 1 2 3 6 7 8 8 9 10 */

转载请注明原文地址: https://www.6miu.com/read-46091.html

最新回复(0)