[CSP-S模擬測試]:二叉搜索樹(DP+貪心)


題目傳送門(內部題99)


輸入格式

  第一行一個整數$n$,第二行$n$個整數$x_1\sim x_n$。


輸出格式

  一行一個整數表示答案。


樣例

樣例輸入:

5
8 2 1 4 3

樣例輸出:

35


數據范圍與提示

樣例解釋:

數據范圍:

  對於$10\%$的數據,$n\leqslant 10$。
  對於$40\%$的數據,$n\leqslant 300$。
  對於$70\%$的數據,$n\leqslant 2,000$。
  對於$100\%$的數據,$n\leqslant 5,000,1\leqslant x_i\leqslant 10^9$。

提示:

  二叉搜索樹或者是一棵空樹,或者是具有下列性質的二叉樹:若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;它的左、右子樹也分別為二叉搜索樹。


題解

因為滿足二叉搜索樹的性質,所以一棵子樹里的點一定是連續的。

考慮$DP$,不妨一步一步來考慮,設$dp[x][l][r]$表示區間$[l,r]$的跟節點深度為$x$的最小代價。

轉移很簡單,無非就是枚舉$[l,r]$中哪個點做跟節點即可,時間復雜度是$\Theta(n^4)$的。

(考慮一個小優化:因為深度其實遠遠達不到$n$,也就是$\log n$多一點,所以直接掃到$10$左右就能拿到$40$分啦~)

考慮優化,發現深度每增加$1$,也就相當於又加了一個$\sum \limits_{i=l}^r x_i$,用前綴和優化就有了$\Theta(n^3)$的做法了。

接着優化,考慮貪心,因為決策點一定是單調的,做個解釋,假設現在要處理區間$[l,r]$,在處理它之前我們已經處理出來了$[l,r-1]$和$[l+1,r]$,並且知道了它們的最優決策點,那么$[l,r]$的最優決策點一定在$[l,r-1]$和$[l+1,r]$的最優決策點之間。

時間復雜度:$\Theta(n^2)$(均攤)。

期望得分:$100$分。

實際得分:$100$分。


代碼時刻

#include<bits/stdc++.h>
using namespace std;
int n;
long long v[5001],s[5001];
pair<long long,int> dp[5001][5001];
int main()
{
	memset(dp,0x3f,sizeof(dp));
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&v[i]);
		s[i]=s[i-1]+v[i];
		dp[i][i]=make_pair(v[i],i);
	}
	for(int i=2;i<=n;i++)
	{
		for(int l=1;l<=n-i+1;l++)
		{
			int r=l+i-1;
			for(int mid=dp[l][r-1].second;mid<=dp[l+1][r].second;mid++)
			{
				long long res=s[r]-s[l-1];
				if(l<=mid-1)res+=dp[l][mid-1].first;
				if(mid+1<=r)res+=dp[mid+1][r].first;
				if(res<dp[l][r].first)dp[l][r]=make_pair(res,mid);
			}
		}
	}
	printf("%lld",dp[1][n]);
	return 0;
}

rp++


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM