教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,可是教主花园的土壤很特别,每一个位置适合种的树都不同,一些树可能会由于不适合这个位置的土壤而损失观赏价值。数组
教主最喜欢3种树,这3种树的高度分别为10,20,30。教主但愿这一圈树种得有层次感,因此任何一个位置的树要比它相邻的两棵树的高度都高或者都低,而且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高。函数
输入文件garden.in的第1行为一个正整数n,表示须要种的树的棵树。spa
接下来n行,每行3个不超过10000的正整数ai,bi,ci,按顺时针顺序表示了第i个位置种高度为10,20,30的树能得到的观赏价值。设计
第i个位置的树与第i+1个位置的树相邻,特别地,第1个位置的树与第n个位置的树相邻。code
输出格式:输出文件garden.out仅包括一个正整数,为最大的观赏价值和。blog
4 1 3 2 3 1 2 3 1 2 3 1 2
11
【样例说明】ci
第1~n个位置分别种上高度为20,10,30,10的树,价值最高。string
【数据规模与约定】io
对于20%的数据,有n≤10;class
对于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 }