D. Jongmah

题目

题意:

    有n个数,对于每个数i,可以自己用3个来形成一个答案,或者是用连续的3个数形成一个答案。输出最多的答案数。
     1 n , m 1 0 6 , 1 a i m 1≤n,m≤10^6,1≤a_i≤m

分析:

    对于每一个元素,它只有三种状态:1:[i-2,i-1,i]、2:[i-1,i,i+1]、3:[i,i+1,i+2]。并且这三种状态均不超过3种,如果超过就直接用每个元素自己的3个就可以了。既然每个元素只有3种状态,那么我们就可以用动态规划了。dp[i][j][k][l]表示考虑[1…i]且i的第1种状态有j个,第二个状态有k个,第三个状态有l个的最多方案数。我们注意到,第一种状态可以用前一个元素的第2中状态表示,并且第一种状态不会对后面的答案产生影响,是无用状态,所以我们就省略了这一层的枚举。
    考虑转移,dp[i][k[l] = dp[i-1][j][k]+l+(cnt[i]-j-k-l)/3。当前状态的三个状态,有两个状态由前面的转移,剩下的一个状态枚举出来即可。

#include <iostream>
using namespace std;

int dp[1000005][3][3],num[1000005]; 

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		int x;
		cin >> x;
		num[x] ++;
	}
	for (int i = 1; i <= m; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			for (int k = 0; k < 3; k++)
			{
				for (int l = 0; l < 3 && j + k + l <= num[i]; l++)
				{
					dp[i][k][l] = max(dp[i][k][l],dp[i-1][j][k] + l + (num[i] - j - k - l) / 3);
				}
			}
		}
 	}
 	cout << dp[m][0][0] << '\n';
	return 0;
}

发布了132 篇原创文章 · 获赞 6 · 访问量 7933

猜你喜欢

转载自blog.csdn.net/weixin_44316314/article/details/104804627
今日推荐