[SDOI2008]Sue的小球(区间Dp)
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                [SDOI2008]Sue的小球(区间Dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                [SDOI2008]Sue的小球
區間DPDPDP。
題目
這一道題的區間DPDPDP還是比較顯然:首先可以考慮開始的總的答案是所有的初速度的和,之后再在收集的過程中逐漸減少答案,最后得到的答案最大。同時又由于速度都是線性減少的,那么dp[i][j]dp[i][j]dp[i][j]很明顯就應該表示從iii到jjj這一段區間表示的答案(也就是答案減少的最小值)。這里,注意到轉移方程中既可以從左邊的點與右邊的區間轉移,又可以從右邊的點與左邊的區間轉移,這樣不妨設dp[i][j]dp[i][j]dp[i][j]表示區間為[i,j][i, j][i,j]同時人在jjj這一個位置的時候的答案減少最小值。
新的問題出來了,就是最重要的部分。
我們在轉移的時候需要使用新的節點的速度?*?已經經過的時間,但是已經經過的時間顯得非常難維護(非要使用pairpairpair也可以),這里注意到所有的小球都是要接住的,那么對于某一段區間,這一段區間外面的小球也一定會下降這個區間答案所使用的時間,于是我們可以在統計區間[i,j][i, j][i,j]的時候同時把位于區間[1,i?1]&[j+1,n][1, i - 1] \& [j + 1, n][1,i?1]&[j+1,n]的小球的答案減少也統計到這里面來。
離散化等簡單的操作就不說了。
代碼:
#include <bits/stdc++.h> using namespace std; const int N = 1000 + 5; int n, x0; struct Egg {int x, y, v;Egg (int a, int b, int c) {x = a;y = b;v = c;}Egg () {} }info[N]; int num[N]; inline int Abs (int u) {return u < 0 ? -1 * u : u; } inline int Find (int u) {int l = 1, r = n, mid;while (l < r) {mid = (l + r) / 2;if (num[mid] < u) {l = mid + 1;}else {r = mid;}}return l; } int dp[N][N], sum[N], tot; bool cmp (Egg m, Egg n) {return m.x < n.x; } int main () {#ifdef wllfreopen ("testdata.in", "r", stdin);#endifmemset (dp, 127, sizeof (dp));scanf ("%d%d", &n, &x0);for (int i = 1; i <= n; ++i) {scanf ("%d", &info[i].x);num[i] = info[i].x;}for (int i = 1; i <= n; ++i) {scanf ("%d", &info[i].y);tot += info[i].y;}for (int i = 1; i <= n; ++i) {scanf ("%d", &info[i].v);}sort (info + 1, info + n + 1, cmp);sort (num + 1, num + n + 1);for (int i = 1; i <= n; ++i) {sum[i] = sum[i - 1] + info[i].v;}for (int i = 1; i <= n; ++i) {info[i].x = Find (info[i].x);dp[i][i] = sum[n] * Abs (x0 - num[info[i].x]);}for (int k = 1; k <= n; ++k) {for (int i = 1; i <= n - k + 1; ++i) {int j = i + k - 1;dp[i][j] = min (dp[i][j], dp[i][j - 1] + (num[info[j].x] - num[info[j - 1].x]) * (sum[n] - sum[j - 1] + sum[i - 1]));dp[i][j] = min (dp[i][j], dp[j - 1][i] + (num[info[j].x] - num[info[i].x]) * (sum[n] - sum[j - 1] + sum[i - 1]));dp[j][i] = min (dp[j][i], dp[j][i + 1] + (num[info[i + 1].x] - num[info[i].x]) * (sum[n] - sum[j] + sum[i]));dp[j][i] = min (dp[j][i], dp[i + 1][j] + (num[info[j].x] - num[info[i].x]) * (sum[n] - sum[j] + sum[i]));}}printf ("%.3lf\n", (tot - min (dp[1][n], dp[n][1])) / 1000.0);return 0; }總結
以上是生活随笔為你收集整理的[SDOI2008]Sue的小球(区间Dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 机器人总动员主角简笔画_机器人总动员简笔
 - 下一篇: ktv点歌系统 Vue +Express