题解 CF1154F 【Shovels Shop】

\[\huge\texttt{Description} \]

日期 \(\texttt{2020}\)\(\texttt{9}\)\(\texttt{8}\)
编号 \(\texttt{CF1154F}\)
算法 Dp前缀和与差分贪心
来源 无名小题

\[\huge\texttt{Solution} \]

这道题目我们可以用\(Dp\)来解决。
我们容易想到这道题目的一个贪心:买最便宜的那几双鞋。
这应该是不难想的。
\(Dp\)题,我们就得设状态。
我们也不难想到,可以设\(Dp_i\)表示前\(i\)双鞋的\(Cost_{Min}\)
然后应该就比较好转移了。
首先,我们的\(Dp_i\)一定是从前面的一个\(Dp_j\)转移过来。
然后略加思考,用一个前缀和,算出\(Dp_i\)\(Dp_j\)要多付的钱,转一下即可。
转移方程就是:

\[Dp_i=\min_{j=0}^{i-1}\{Dp_j+Prefix_i-Prefix_{j+Free_{i-j}}\}; \]

\[\huge\texttt{Code} \]

#include<bits/stdc++.h>
using namespace std;
int Total,Sale,Buy;
int Array[200001];
int Prefix[200001];
int Free[200001];
int Dp[200001];
int main(void)
{
	register int i,j;
	cin>>Total>>Sale>>Buy;
	for(i=1;i<=Total;i++)
	{
		cin>>Array[i];
	}
	sort(Array+1,Array+Total+1);
	for(i=1;i<=Total;i++)
	{
		Prefix[i]=Prefix[i-1]+Array[i];
	}
	for(i=1;i<=Sale;i++)
	{
		register int X,Y;
		cin>>X>>Y;
		Free[X]=max(Free[X],Y);
	}
	for(i=1;i<=Buy;i++)
	{
		Dp[i]=0x7ffffff;
	}
	Dp[0]=0;
	for(i=1;i<=Buy;i++)
	{
		for(j=0;j<i;j++)
		{
			Dp[i]=min(Dp[i],Dp[j]+Prefix[i]-Prefix[j+Free[i-j]]);
		}
	}
	cout<<Dp[Buy]<<endl;
	return 0;
}
posted @ 2020-09-08 20:05  Bushuai_Tang  阅读(164)  评论(0编辑  收藏  举报