「杂题乱刷」CF1987D

题目链接

CF1987D World is Mine

提示

  1. Alice 的策略是固定的。

  2. 考虑用动态规划解决问题。

解题思路

我们发现,Alice 的最优策略一定是每次取当前能取的美味值最小的蛋糕,而 Bob 的策略难以使用贪心维护。

于是我们考虑用动态规划来考虑 Bob 的策略。

我们发现,Bob 想让让 Alice 吃不到某种蛋糕,当且仅当 Bob 把这个种类的所有蛋糕都拿走了。因此我们需要开个桶来记录每个种类的蛋糕所出现的数量。

于是我们就可以将 Bob 蛋糕的个数加 \(1\) 化为 Bob 拿蛋糕的代价(加上一是因为 Alice 是先手),而 \(1\) 就是 Bob 获得的收益,于是我们就可以直接 dp,\(dp_{i,j}\) 表示 Bob 考虑到前 \(i\) 个蛋糕,花的代价为 \(j\) 时可以拿掉的最大蛋糕种类数是多少。

最终答案即为直接用原本的蛋糕种类数减去 Bob 最大拿掉的蛋糕种类数。

时间复杂度 \(O(n^2)\)

参考代码

点击查看代码
/*
Tips:
你数组开小了吗?
你MLE了吗?
你觉得是贪心,是不是该想想dp?
一个小时没调出来,是不是该考虑换题?
打 cf 不要用 umap!!!

记住,rating 是身外之物。

该冲正解时冲正解!

Problem:

算法:

思路:

*/
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define lc(x) x<<1
#define rc(x) x<<1|1
#define mid ((l+r)>>1)
#define cin(x) scanf("%lld",&x)
#define cout(x) printf("%lld",x)
#define lowbit(x) (x&-x)
#define pb push_back
#define pf push_front
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) x/__gcd(x,y)*y
#define Sum(x,y) 1ll*(x+y)*(y-x+1)/2
#define aty cout<<"Yes\n";
#define atn cout<<"No\n";
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
#define xxy cout<<"yes\n";
#define xxn cout<<"no\n";
#define printcf(x) x?cout<<"YES\n":cout<<"NO\n";
#define printat(x) x?cout<<"Yes\n":cout<<"No\n";
#define printxx(x) x?cout<<"yes\n":cout<<"no\n";
ll t;
ll n;
ll a[5010];
ll b[5010];
ll c[5010],d[5010];
ll pd,ans;
ll lst,k;
ll dp[5010][5010];
/*
A选此时最小的

B选此时值最大且数量最少的 

dp!!!!

你发现每个东西有你需要拿的时间

还有什么时候之前你要拿掉

dp[i][j]表示第i个蛋糕,使用了j个时间的干掉的最大蛋糕数 
*/
/*
1  2  3  5  6  9
2  3  3  2  5  2

hack:
10
4
1 4 2 3
3
1 1 1
5
1 4 2 3 4
4
3 4 1 4
1
1
8
4 3 2 5 6 8 3 4
7
6 1 1 3 5 3 1
11
6 11 6 8 7 5 3 11 2 3 5
17
2 6 5 3 9 1 6 2 5 6 3 2 3 9 6 1 6
11
1 2 2 2 3 3 3 4 4 4 5
*/
void solve()
{
	pd=1,k=0;
	cin>>n;
	forl(i,1,n)
		cin>>a[i],b[a[i]]++;
	forl(i,1,5000)
		if(b[i])
			k++,c[k]=k,d[k]=b[i]+1;
	forl(i,1,k)
	{
		forr(j,i,0)
		{
			dp[i][j]=max(dp[i][j],dp[i-1][j]);
			if(j+d[i]<=i)
				dp[i][j+d[i]]=max(dp[i][j+d[i]],dp[i][j]+1);
		}
		
	}
	ll ma=0;
	forl(i,1,k)
	{
		forl(j,0,i)
	/*		cout<<"["<<i<<','<<j<<']'<<dp[i][j]<<' ',*/ma=max(ma,dp[i][j]),dp[i][j]=0;
	//	cout<<endl;
	}
	cout<<k-ma<<endl;	
	forl(i,1,5000)
		a[i]=b[i]=c[i]=d[i]=0;
/*	while(1)
	{
		if(pd)
		{
			forl(i,1,5000)
			{
				if(b[i])
				{
					b[i]--;
					ans++;
					lst=i;
					break;			
				}
				if(i==5000)
				{
					cout<<ans<<endl;
					return ;
				}
			}
			pd^=1;
		}
		else
		{
			ll mi=1e18,id=0,sum=0;
			forl(i,lst+1,5000)
			{
				if(b[i])
					c[]
			}
			pd^=1;
		}
	}*/
}
int main()
{
	IOS;
	t=1;
 	cin>>t;
	while(t--)
		solve();
    /******************/
	/*while(L<q[i].l) */
	/*    del(a[L++]);*/
	/*while(L>q[i].l) */
	/*    add(a[--L]);*/
	/*while(R<q[i].r) */
	/*	  add(a[++R]);*/
	/*while(R>q[i].r) */
	/*    del(a[R--]);*/
    /******************/
	QwQ;
}
posted @ 2024-07-01 02:26  wangmarui  阅读(25)  评论(0编辑  收藏  举报