新生多校第6场 LLM找对象(DP+离散化)

新生多校第6场 LLM找对象(DP+离散化)_第1张图片

题解:

dp[i][j][0]:前i天已经j天不穿拖鞋且第i天穿了拖鞋的最大值

dp[i][j][1]:前i天已经j天不穿拖鞋且第i天没穿拖鞋的最大值

状态转移:

dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]);

dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-1][0]+d[i]);(d[i]表示第i天有多少个妹子)

#include
#include       
#include              
#include              
#include      
#include    
#include     
#include              
#include              
#include              
#include      
#include     
#include      
using namespace std;
typedef long long ll;
#define inf  1000000000         
#define mod 1000000007               
#define maxn  1705   
#define PI acos(-1.0) 
#define lowbit(x) (x&-x)   
#define eps 1e-9  
int dp[maxn][maxn][2], a[maxn*100], b[maxn*100], c[maxn*100], d[maxn*100];
int main(void)
{
	int n, k, i, j, cnt, p;
	while (scanf("%d%d", &n, &k) != EOF)
	{
		cnt = 0;p = 1;
		memset(a, 0, sizeof(a));
		memset(c, 0, sizeof(c));
		memset(d, 0, sizeof(d));
		memset(dp, 0, sizeof(dp));
		for (i = 1;i <= n;i++)
			scanf("%d", &a[i]), b[i] = a[i];
		k = min(k, n);
		sort(b + 1, b + n + 1);
		int num = unique(b + 1, b + n + 1) - b - 1;
		c[1] = b[1];cnt = 1;
		for (i = 2;i <= num;i++)
		{
			if (b[i] - b[i - 1] > 1)
				c[++cnt] = b[i] - 1;
			c[++cnt] = b[i];
		}
		for (i = 1;i <= n;i++)
			a[i] = lower_bound(c + 1, c + cnt + 1, a[i]) - c;
		sort(a + 1, a + n + 1);
		for (i = 1;i <= max(n, cnt);i++)
			d[a[i]]++;
		for (i = 1;i <= max(cnt, n);i++)
		{
			for (j = 1;j <= k;j++)
			{
				if (j > i)
					break;
				dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1]);
				dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - 1][0] + d[i]);
			}
		}
		int ans=0, tmp;
		for (i = 0;i <= k;i++)
		{
			tmp = max(dp[max(n, cnt)][i][1], dp[max(n, cnt)][i][0]);
			ans = max(ans, tmp);
		}
		printf("%d\n", ans);
	}
	return 0;
}


你可能感兴趣的:(DP,dp)