1. 程式人生 > >洛谷-【動態規劃】- P2858 [USACO06FEB]奶牛零食Treats for the Cows

洛谷-【動態規劃】- P2858 [USACO06FEB]奶牛零食Treats for the Cows

題目描述

FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for giving vast amounts of milk. FJ sells one treat per day and wants to maximize the money he receives over a given period time.

The treats are interesting for many reasons:The treats are numbered 1..N and stored sequentially in single file in a long box that is open at both ends. On any day, FJ can retrieve one treat from either end of his stash of treats.Like fine wines and delicious cheeses, the treats improve with age and command greater prices.The treats are not uniform: some are better and have higher intrinsic value. Treat i has value v(i) (1 <= v(i) <= 1000).Cows pay more for treats that have aged longer: a cow will pay v(i)*a for a treat of age a.Given the values v(i) of each of the treats lined up in order of the index i in their box, what is the greatest value FJ can receive for them if he orders their sale optimally?

The first treat is sold on day 1 and has age a=1. Each subsequent day increases the age by 1.

約翰經常給產奶量高的奶牛發特殊津貼,於是很快奶牛們擁有了大筆不知該怎麼花的錢.為此,約翰購置了N(1≤N≤2000)份美味的零食來賣給奶牛們.每天約翰售出一份零食.當然約翰希望這些零食全部售出後能得到最大的收益.這些零食有以下這些有趣的特性:

•零食按照1..N編號,它們被排成一列放在一個很長的盒子裡.盒子的兩端都有開口,約翰每

天可以從盒子的任一端取出最外面的一個.

•與美酒與好吃的乳酪相似,這些零食儲存得越久就越好吃.當然,這樣約翰就可以把它們賣出更高的價錢.

•每份零食的初始價值不一定相同.約翰進貨時,第i份零食的初始價值為Vi(1≤Vi≤1000).

•第i份零食如果在被買進後的第a天出售,則它的售價是vi×a.

Vi的是從盒子頂端往下的第i份零食的初始價值.約翰告訴了你所有零食的初始價值,並希望你能幫他計算一下,在這些零食全被賣出後,他最多能得到多少錢.

輸入輸出格式

輸入格式:

Line 1: A single integer, N

Lines 2..N+1: Line i+1 contains the value of treat v(i)

輸出格式:

Line 1: The maximum revenue FJ can achieve by selling the treats

輸入輸出樣例

輸入樣例#1: 複製

5
1
3
1
5
2

輸出樣例#1: 複製

43

說明

Explanation of the sample:

Five treats. On the first day FJ can sell either treat #1 (value 1) or treat #5 (value 2).

FJ sells the treats (values 1, 3, 1, 5, 2) in the following order of indices: 1, 5, 2, 3, 4, making 1x1 + 2x2 + 3x3 + 4x1 + 5x5 = 43.

import java.util.*;
/*
 *奶牛零食
 */
public class Main{
	static int[] a;
	static int res=0;
	/**
	 * 常規的遞迴
	 */
	public static void dfs(int st,int l,int r,int sum) {
		if(l==r) {
			res=Math.max(res, sum+a[l]*st);
			return;
		}
		dfs(st+1,l+1,r,sum+a[l]*st);
		dfs(st+1,l,r-1,sum+a[r]*st);
	}
	static int[][] f;
	/**
	 * 記憶化搜尋 f[l][r]表示l到r這個區間能得到的最大值
	 * 
	 */
	public static int dfs(int st,int l,int r) {
		if(r<l)
			return 0;
		if(f[l][r]!=0)
			return f[l][r];
		f[l][r]=Math.max(dfs(st+1,l+1,r)+st*a[l],dfs(st+1,l,r-1)+st*a[r]);
		return f[l][r];
	}
	public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        a=new int[n+1];
        f=new int[n+1][n+1];
        for(int i=1;i<=n;i++) {
        	a[i]=in.nextInt();
        	f[i][i]=a[i]*n;
        }
        /**
         * 動規解法
         */
        for(int i=2;i<=n;i++) {
        	for(int l=1;l<=n;l++) {
        		int r=l+i-1;
        		if(r>n)
        			break;
        		f[l][r]=Math.max(f[l+1][r]+a[l]*(n-i+1), f[l][r-1]+a[r]*(n-i+1));
        	}
        }
        System.out.println(f[1][n]);
        //dfs(1,1,n);
        //System.out.println(f[1][n]);
        //dfs(1,1,n,0);
        //System.out.println(res);
    }
}