我是看了这位大神写的http://m.blog.csdn.net/article/details?id=51477402
但是他没有做详细的解释,我来以我的理解解释一下。
首先对于区间(1,n)我们找到最小值min和最大值max,则ans[n]=min*max。
记录下min的位置minw,开始递归(1,minw-1)和(minw+1,n)
我称之为左右区间,区间大小为L和R,接下来是重点。
对于区间大小为 max(L,R) 至 n-1 的区间来说,他们必须包含区间(1,n)的最小值
而且他们能包含到区间(1,n)的最大值,所有他们的价值为(1,n)的价值。
对于区间大小为 L 至 R 的区间来说他们可以包含(1,n)的最小值也可以不包含。
选择不包含最小值的区间递归会把他的答案更新,选择包含的区间递归可能更新不到。
比如以下数据 8 22 54 7 89 45 , 7 89 45 的价值比 8 22 54 要大,但是递归为 8 22 54 和 89 45
更新不到 7 89 45 但是对于ans[4]一定可以包含 7和89,
以上就是为了解释代码
ans[i]=max(ans[i],ans[i+1]);
是如何工作的。
下面贴上java代码:
import java.util.Scanner;
/*
* 15
* 2 3 5 7 8 22 54 7 89 45 2 1 5 6 9
*/
public class Code {
public static long ans[]=new long[100005];
public static long arr[]=new long[100005];
public static int n;
public static void main(String args[]){
Scanner in=new Scanner(System.in);
while(true){
try {
n=in.nextInt();
for(int i=1;i<=n;i++){
arr[i]=in.nextLong();
}
} catch (Exception e) {
break;
}
for(int i=1;i<=100000;i++)
ans[i]=0;
f(1,n);
for(int i=n-1;i>=1;i--){
/*if(ans[i]==0)
ans[i]=ans[i+1];*/
//ans[i]=Math.max(ans[i],ans[i+1]);
}
for(int i=1;i<=n;i++);
//System.out.println(ans[i]);
}
}
public static void f(int l,int r){
if(!(r>=l&&1<=l&&r<=n)) return;
for(int i=l;i<=r;i++)
System.out.print(arr[i]+" ");
System.out.println();
if(l==r&&arr[l]*arr[r]>ans[1]) {
ans[1]=arr[l]*arr[r];
return;
}
long min=Integer.MAX_VALUE;
long max=Integer.MIN_VALUE;
int minw=0;
for(int i=l;i<=r;i++){
if(arr[i]>max) max=arr[i];
if(arr[i]<min){
min=arr[i];
minw=i;
}
}
if(min*max>ans[r-l+1]) ans[r-l+1]=max*min;
f(l,minw-1);
f(minw+1,r);
}
}