P1133 教主的花园-动态规划

本文探讨了在环形花园中种植三种不同高度树木的问题,旨在寻找最优布局以最大化观赏价值。通过动态规划方法,文章详细阐述了如何设计算法以确保树木间高度的层次感,同时考虑土壤特性和树种限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值。

教主最喜欢33种树,这3种树的高度分别为10,20,30。教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高

 https://www.luogu.org/problemnew/show/P1133

刚看到这道题的环形,我不禁想到了区间dp,但是看到后面发现每次种树只与之前的那棵树种的什么有关,好像无法区间dp;

这样就像到了f[i]表示以i点结尾的最高价值,这样状态无法转移,因为没有考虑树的种类和最高(最低),那么就再开两维;

状态:f[i][j][k]表示第i个点种j树,k==0表示比两边低,k==1表示比两边高。(1=<j<=3,0=<k<=1)

初始化:全部归零,枚举第一个点种哪种树。

转移

f[i][1][0]=max(f[i-1][2][1],f[i-1][3][1])+a[i][1];(种10树最低,从20树、30树转移来)
f[i][2][0]=f[i-1][3][1]+a[i][2];(种20树最低,从30树转移来)
f[i][2][1]=f[i-1][1][0]+a[i][2];(种20树最高,从10树转移来)
f[i][3][1]=max(f[i-1][1][0],f[i-1][2][0])+a[i][3];(种30树最高,从10树、20树转移来)

因为还要考虑n和1的关系。

在每一次枚举起点后,枚举终点的最大值并用ans记录,枚举的终点状态范围由起点状态决定(自行理解)。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int f[100001][4][2];
int a[100001][4];
int n,ans;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&a[i][1],&a[i][2],&a[i][3]);
	}
	for(int j=1;j<=3;j++){
		for(int i=1;i<=3;i++){
			for(int k=0;k<=1;k++){
				f[1][i][k]=0;
			}
		}
		f[1][j][1]=f[1][j][0]=a[1][j];
		for(int i=2;i<=n;i++){
			f[i][1][0]=max(f[i-1][2][1],f[i-1][3][1])+a[i][1];
			f[i][2][0]=f[i-1][3][1]+a[i][2];
			f[i][2][1]=f[i-1][1][0]+a[i][2];
			f[i][3][1]=max(f[i-1][1][0],f[i-1][2][0])+a[i][3];
		}
		for(int i=1;i<=j-1;i++){
			ans=max(ans,f[n][i][0]);
		}
		for(int i=3;i>=j+1;i--){
			ans=max(ans,f[n][i][1]);
		}
	}
	printf("%d",ans);
	return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值