zoukankan      html  css  js  c++  java
  • 链家2018链习生招聘 编程题三

    小明有n(1<=n<=2000)个美味的食物,他想卖掉他们来赚钱,这些书屋放在一些箱子里,它们有些有趣的特性:
    (1)这些食物被编号1~n,每一天小明都可以从这排箱子的头部或者尾部取出食物去买
    (2)这些食物放得越久,年龄越大,价值越大,食物i有一个厨师的价值V(i)
    (3)放了a天后,年龄为a,食物最终的价值为V(i)xa
    给定每一个食物的初始价值V(i),求出小明卖掉他们后能获得的最大价值,第一天出售的食物的年龄为1此后,每增加一天食物的年龄就增加1
    提示
    样例说明:小明出售这些食物(初始值为1,3,1,5,2)的顺序为:第一天卖掉第一个,第二天卖掉第5个,第三天卖掉第2个,第四天卖掉第3个,第五天卖掉第4个。获得的最大价值 1x1 + 2x2 + 3x3 + 4x1 + 5x5 = 43

    输入
    第一行,一个整数n
    第i+1行:每行为食物i的初始价值V(i)

    ···
    输入样例
    5
    1
    3
    1
    5
    2
    输出样例
    43
    ···

    思路:
    看样子dfs一下就可以,但是数据量2000,必然不能暴力 ,由于这道题目要求卖掉最后一个或者最前一个食物,不同的取法会得到不同的区间,最后直到剩下一个食物[i,i]。
    可以考虑区间dp 。那么最优子结构是什么呢?
    最优子结构不就是区间上的最大值吗,下一个状态 = 当前的状态左+v[i] 或 右+v[j]转移得到,所以得到
    dp[i][j] = max(dp[i][j-1]+v[j],dp[i+1][j]+v[i]) 这里的v是年数*初始值
    但是这种dp的时间复杂度是O(n^3),由于本题目的特殊性,即长度为x的区间只能由长度为x-1的区间和长度为1的区间合并得到。所以这里的dp可以写成

    dp[p][i] = max(dp[p-1][i] + v[i+p-1]*(n-p+1), dp[p-1][i+1]+v[i]*(n-p+1));
    

    代码如下

    #include <bitsstdc++.h>
    using namespace std;
    int dp[2010][2010];
    int main() {
    	int n;
    	while (cin >> n) {
    		vector<int> v(n);
    		memset(dp, 0, sizeof dp);
    		for (int i = 0; i < n; ++i) cin >> v[i];
    		// dp[p][i] 以i开始 长度为p能得到的最大值 
    		for (int p = 1; p <= n; ++p) {
    			for (int i = 0; i <= n - p; ++i) {
    				dp[p][i] = max(dp[p-1][i] + v[i+p-1]*(n-p+1), dp[p-1][i+1]+v[i]*(n-p+1));
    			}
    		}
    		cout << dp[n][0] << endl;
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    (六)键盘事件
    (五)鼠标事件
    (四)WebDriver常用方法
    等价类,边界值,判定图实例
    WCF入门(三)---WCF与Web服务/Web Service
    WCF入门(二)-----实战开发
    C#中用JavaScriptSerializer和Json.Net操作json格式的文件
    C#中SaveFileDialog 和OpenFileDialog 的用法
    C#操作.csv文件Demo
    Excel操作--使用NPOI导入导出Excel为DataTable
  • 原文地址:https://www.cnblogs.com/pk28/p/7470030.html
Copyright © 2011-2022 走看看