小明有n(1≤n≤2000)个美味的食物,他想卖掉它们来赚钱。这些食物放在一些箱子里,它们有些有趣的特性:
(1)这些食物被编号1~n,每一天小明可以从这排箱子的头部或者尾部取出食物去卖;
(2)这些食物放的越久,年龄越大,价值越大,食物i有一个初始的价值V(i);
(3)放了a天后,年龄为a,食物最终价值为V(i)xa。
给定每一个食物的初始价值V(i),请求出小明卖掉它们后可以获得的最大价值,第一天出售的食物年龄为1,此后每增加一天食物的年龄就加1。
小明有n(1≤n≤2000)个美味的食物,他想卖掉它们来赚钱。这些食物放在一些箱子里,它们有些有趣的特性:
(1)这些食物被编号1~n,每一天小明可以从这排箱子的头部或者尾部取出食物去卖;
(2)这些食物放的越久,年龄越大,价值越大,食物i有一个初始的价值V(i);
(3)放了a天后,年龄为a,食物最终价值为V(i)xa。
给定每一个食物的初始价值V(i),请求出小明卖掉它们后可以获得的最大价值,第一天出售的食物年龄为1,此后每增加一天食物的年龄就加1。
第1行:一个整数n;
第i+l行:每行食物i的初始价值V(i)。
1行:小明最终可以获得的最大价值。
5 1 3 1 5 2
43
小明出售这些食物(初始价值1,3,1,5,2)的顺序为:第一天卖掉1个,第二天卖掉5个,第三天卖掉2个,第四天卖掉3个,第五天卖掉4个,获得最大的价值1x1+2x3+3x3+4x1+5x5=43。
//java双端队列 import java.util.*; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 while (in.hasNextInt()) { // 注意 while 处理多个 case int a = in.nextInt(); Deque<Integer> deque = new LinkedList<>(); for(int i=0;i<a;i++) deque.offerLast(in.nextInt()); System.out.println(caculate(deque)); } } public static int caculate(Deque<Integer> deque){ int sum = 0,day = 1; while(!deque.isEmpty()){ if(deque.peekFirst() < deque.peekLast()){ sum += day * deque.pollFirst(); day ++; }else{ sum += day * deque.pollLast(); day ++; } } return sum; } }
用两个指针指向头尾,每次都取较小值加上去。因为要获得最大值而且每次只能操作头尾,所以较大的值放在后面计算肯定会取得最优解。
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] v = new int[n]; for (int i = 0; i < n; i++) { v[i] = sc.nextInt(); } int head = 0; int tail = n - 1; int sum = 0; int day = 1; while (head <= tail) { if (v[head] < v[tail]) { sum += day * v[head++]; } else { sum += day * v[tail--]; } day++; } System.out.println(sum); } }