首页 > 代码库 > 动规-POJ-3186
动规-POJ-3186
http://poj.org/problem?id=3186
Treats for the Cows
给定一个双端队列dq,其中有n个正整数元素。
每次可从dq头或者尾中取出1个元素。
第i次(从1开始计数)取出的元素能带来的权值为i*元素值。
问能取得的最大权值。
解题报告
思路
假设现在的状态为双端队列的首部元素为原队列中的第l个元素,尾部元素为原队列中的第r个元素,记状态为(l, r)。
那么状态(l, r)可向(l+1, r)与(l, r-1)转移,且无后效性。
那么可用类似SPFA的方式进行dp:
定义队列q。
初始化时将状态(1, n)加入队列。
队列不为空时循环:
取出队首元素,尝试更新可转移的状态。
如果状态被更新,且不在队列中,则加入队列。
(当l==r时要特判,同时记录解)
取最小的解输出。
(其实这个做法还是相当诡异,权当参考)
代码
#include <cstring> #include <iostream> #include <queue> using namespace std; const int maxn = 2003; int n; int dp[maxn][maxn] = {0}, book[maxn][maxn] = {0}; int val[maxn]; int ans[maxn] = {0}; queue<pair<int, int> > q; int main() { for (int i = 1; i <= n; i++) { cin >> val[i]; } q.push(make_pair(1, n)); book[1][n] = 1; while (!q.empty()) { int l = q.front().first, r = q.front().second; q.pop(); book[l][r] = 0; if (l == r) { ans[l] = max(ans[l], dp[l][r] + val[l] * n); continue; } if (dp[l + 1][r] < dp[l][r] + val[l] * (n - r + l)) { dp[l + 1][r] = dp[l][r] + val[l] * (n - r + l); if (book[l + 1][r] == 0) { book[l + 1][r] = 1; q.push(make_pair(l + 1, r)); } } if (dp[l][r - 1] < dp[l][r] + val[r] * (n - r + l)) { dp[l][r - 1] = dp[l][r] + val[r] * (n - r + l); if (book[l][r - 1] == 0) { book[l][r - 1] = 1; q.push(make_pair(l, r - 1)); } } } int maxAns = 0; for (int i = 1; i <= n; i++) { maxAns = max(maxAns, ans[i]); } cout << maxAns << endl; return 0; }
--(完)--
动规-POJ-3186
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。