P1040 加分二叉树(区间DP&记忆化搜索)

P1040 加分二叉树(区间DP&记忆化搜索)

传送门

思路:超级经典的区间 d p dp 题。也可用记忆化搜索做,简单来说就是枚举树根,然后不断向外扩展,打印先序遍历就用“根左右“的方式递归就 O K OK 了。注意题目要求空子树是1.

e p : 23 ep: 23 2 2 为根,则 2 2 的左子树是空。

区间 d p A C dpAC 代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=35;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
inline void read(int &x){ 
	x=0;int w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar())
		x=(x<<3)+(x<<1)+(ch&15);
	x*=w; 
}
ll dp[N][N];
int n,rt[N][N],x;
void Print(int l,int r){
	if(l>r) return;
	printf("%d ",rt[l][r]);
	Print(l,rt[l][r]-1);
	Print(rt[l][r]+1,r);
}
int main(){
	read(n);
	for(int i=1;i<=n;i++) read(x),dp[i][i]=x,rt[i][i]=i,dp[i][i-1]=1;
	for(int k=2;k<=n;k++)
		for(int l=1;l+k-1<=n;l++){
			 int r=l+k-1;
			 for(int i=l;i<=r;i++){
			 	 ll tmp=dp[l][i-1]*dp[i+1][r]+dp[i][i];
			 	 if(dp[l][r]<tmp){
			 	 	rt[l][r]=i;
			 	 	dp[l][r]=tmp;
				  }
			 }
		}
	printf("%lld\n",dp[1][n]);
	Print(1,n);
	return 0;
}

记忆化搜索 A C AC 代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=35;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
inline void read(int &x){ 
	x=0;int w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar())
		x=(x<<3)+(x<<1)+(ch&15);
	x*=w; 
}
ll ans[N][N];
int n,a[N],rt[N][N];
ll dfs(int l,int r){
	 if(ans[l][r]) return  ans[l][r];
	 if(l>r) return 1;
	 if(l==r){
	 	 rt[l][l]=l;
	 	 return ans[l][l]=a[l];
	 }
	 ll sum=0;
	 for(int i=l;i<=r;i++){
	 	 ll tmp=dfs(l,i-1)*dfs(i+1,r)+a[i];
	 	 if(tmp>sum) sum=tmp,rt[l][r]=i;
	 }
	 return ans[l][r]=sum;
}
void Print(int l,int r){
	if(l>r) return;
	printf("%d ",rt[l][r]);
	Print(l,rt[l][r]-1);
	Print(rt[l][r]+1,r);
}
int main(){
	read(n);
	for(reg int i=1;i<=n;i++) read(a[i]);
	printf("%lld\n",dfs(1,n));
	Print(1,n);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/106630771