洛谷-教主的花园-动态规划
题目描述
教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值。
教主最喜欢3种树,这3种树的高度分别为10,20,30。教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高。
输入输出格式
输入格式:输入文件garden.in的第1行为一个正整数n,表示需要种的树的棵树。
接下来n行,每行3个不超过10000的正整数ai,bi,ci,按顺时针顺序表示了第i个位置种高度为10,20,30的树能获得的观赏价值。
第i个位置的树与第i+1个位置的树相邻,特别地,第1个位置的树与第n个位置的树相邻。
输出格式:输出文件garden.out仅包括一个正整数,为最大的观赏价值和。
输入输出样例
4 1 3 2 3 1 2 3 1 2 3 1 2
11
说明
【样例说明】
第1~n个位置分别种上高度为20,10,30,10的树,价值最高。
【数据规模与约定】
对于20%的数据,有n≤10;
对于40%的数据,有n≤100;
对于60%的数据,有n≤1000;
对于100%的数据,有4≤n≤100000,并保证n一定为偶数。
思路:
这题是典型的三维动规,在这里我用一个三维数组dp[i][j][k]表示前i个已经放的树最大值,i表示当前的第i棵树,j表示当前这个i位置种的树的种类,1表示10m的,2为20m,3为30m的,k表示i这个树和前面一棵树是什么关系,1为上升,0为下降。
由于这个花圃是个环,用约瑟夫环那样的解法未免有点大材小用,我们可以对第2~n棵树进行DP动规,最后特判一下第n棵树和第1棵树的关系与价值,取最优值即可。
特别提示:题目中的n为1~100000,说实话真™大!我们不应该把dp数组放到主函数里面,而应该放到全局变量中,这样就不必要写高精度了O(∩_∩)O~,具体为什么,额~~自行百度把←_←
代码如下:
1 #include<stdio.h> 2 #include<string.h> 3 int max(int a,int b) 4 { 5 return a>b?a:b; 6 } 7 int dp[100002][5][2],c[100002][5]; 8 int main() 9 { 10 int i,j; 11 int n,ans=0; 12 scanf("%d",&n); 13 for(i=1;i<=n;i++) 14 { 15 scanf("%d%d%d",&c[i][1],&c[i][2],&c[i][3]);//输入放三种树的价值 16 } 17 for(i=2;i<=n;i++)//寻找第2-n种情况的DP 18 { 19 dp[i][1][1]=max(dp[i-1][2][0],dp[i-1][3][0])+c[i][1];//种10m的树与之前下降的20m树或者30m树哪个价值大 20 dp[i][2][1]=dp[i-1][3][0]+c[i][2];//种20米的树和前面30m的树是下降状态 21 dp[i][2][0]=dp[i-1][1][1]+c[i][2];//种20米的树和前面10m的树是上升状态 22 dp[i][3][0]=max(dp[i-1][2][1],dp[i-1][1][1])+c[i][3];//种30m的树与之前上升的10m树或者20m树哪个价值大 23 } 24 /*========================================*///最后对第n棵树与第1颗树来个特判即可 25 ans=max(ans,dp[n][1][1]+c[1][2]); 26 ans=max(ans,dp[n][1][1]+c[1][3]); 27 ans=max(ans,dp[n][2][0]+c[1][1]); 28 ans=max(ans,dp[n][2][1]+c[1][3]); 29 ans=max(ans,dp[n][3][0]+c[1][1]); 30 ans=max(ans,dp[n][3][0]+c[1][2]); 31 /*========================================*/ 32 printf("%d\n",ans); 33 return 0; 34 }