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; }
--(完)--