HDU 3045 Picnic Cows(斜率優化DP)

這是個很明顯的DP題目,排序之後容易想到DP方程爲dp【i】 = dp【j】 + w【j + 1,i】

然而4*10^5次方明顯TLE,必須得優化,因爲是一維的狀態表示,所以四邊形優化應該不可行(個人做題太少了,沒見過一維的四邊形優化)

另外w函數和j有關,所以單調隊列不可行了,只能往斜率優化想了,斜率優化證明還算容易吧,證出來之後就相當於模板了



#include<stdio.h>
#include<string.h>
#include<algorithm>
#define INF 0x7ffffffffffLL
#define LL __int64
using namespace std;
const int maxn = 400005;
LL moo[maxn],q[maxn];
LL dp[maxn],sum[maxn];
LL n,m;
LL get_y(LL i,LL j){
	return (dp[i] + (i) * moo[i + 1] - sum[i] ) - (dp[j] + (j) * moo[j + 1] - sum[j]);
}
LL get_x(LL i,LL j){
	return moo[i + 1] - moo[j + 1];
}
LL get_dp(LL j,LL t)
{
	return dp[j] + sum[t] - sum[j] - (t - j) * moo[j + 1];
}
void solve();
int main()
{
	int i;
	while(scanf("%I64d%I64d",&n,&m) != EOF){
		for(i = 1;i <= n;i ++)
			scanf("%I64d",&moo[i]);
		sort(moo + 1,moo + 1 + n);
	/*	for(i = 1;i <= n;i ++)
			printf("%d ",moo[i]);
		putchar('\n');*/
		for(i = 1;i <= n;i ++)
			sum[i] = sum[i - 1] + moo[i];
		memset(dp,0,sizeof(dp));
		solve();
	/*	for(i = 1;i <= n;i ++)
			printf("I:%d    DP:%I64d    get:%I64d\n",i,dp[i],get_dp(0,i));*/
	}
	return 0;
}
void solve()
{
	LL head,tail,i;
	head = tail = 0;
	for(i = 1;i < m; i++)
		dp[i] = INF;
	q[0] = 0;
	for(i = m;i <= n;i ++){
		LL p = i - m;
		while(head < tail){
			LL x1 = get_x(q[tail - 1],q[tail]);
			LL y1 = get_y(q[tail - 1],q[tail]);
			LL x2 = get_x(q[tail],p);
			LL y2 = get_y(q[tail],p);
			if(y1 * x2 >= y2 * x1) tail --;
			else break;
		}
		q[++ tail] = p;
		while(head < tail){
			LL a = get_dp(q[head],i);
			LL b = get_dp(q[head + 1],i);
			if(a > b) head ++;
			else break;
		}
	//	if(i == 7) printf("HEAD:%I64d\n",q[head]);
		dp[i] = get_dp(q[head],i);
	}
	printf("%I64d\n",dp[n]);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章