產品排序 product

    評測傳送門ios

【問題描述】
  你是一個公司的員工,你會按時間順序受到一些產品的訂單,你須要用一個棧來改變這些訂單的順序(每一個產品都必須入棧和出棧一次)。
  按初始順序,每次能夠將一個產品入棧,或將棧頂產品彈至如今的序列末尾。ide

  每一個產品有一個製做時間t i 和單位時間懲罰值d i 。函數

  總的懲罰值爲∑ ni=1 (s i × d i ),其中s i 爲第i個產品的完成時間,你須要最小化總的懲罰值。
輸入】
  輸入文件 product.in。
  第一行一個數n,表示產品個數。
  接下來n行,每行兩個數表示t i , d i 。
輸出】
  輸出文件 product.out。
  一行一個數表示最小的總懲罰值。spa

【樣例輸入】code

  4blog

  1 4
遞歸

  3 2
get

  5 2
string

  2 1
產品

【樣例輸出】

  40

【數據範圍】

  30%: n ≤ 15
  50%: n ≤ 100
  100%: n ≤ 200, t i , d i ≤ 1000

正解:

  f[l][r] : 標號 l~r 的最小懲罰值 (時間上以開始生產[ l , r ]的產品爲起始

  < st[ ] 爲時間前綴和 sd[ ] 爲單位時間懲罰值前綴和>

  在[l,r] 中枚舉 i , i 爲 [l,r]中最後一個出棧的元素 即棧中最後一個元素

  f[l][r]=min(f[l][r],f[l][i-1]+f[i+1][r]+(st[i-1]-st[l-1])*(sd[r]-sd[i])+(st[r]-st[l-1])*d[i]);

  這個轉移方程式我真的想了差很少十分鐘纔看懂

  以下:(必定要仔細,耐心理解 qwq)

  i 爲最後一個出棧的元素 因此 l ~ i-1 必定在 i 進棧前就出棧了(不然它們如今就還在棧中)

  f[l][i-1] 和 f[i+1][r] 都只與它們內部的順序以及 [ l , i ]的總時間有關

  是兩個互不相關的子問題

  (st[r]-st[l-1])*d[i]) 是 i 的懲罰值 很好理解

  (st[i-1]-st[l-1])*(sd[r]-sd[i]) 我以爲是一個很巧妙的地方啊

  我以爲我如今說不清楚 要本身領會一下qwq

  可是我仍是要大概說一下<這裏用記憶化搜索實現的>

      是加法結合律的逆向運用

      而後保證了計算f[i+1][r]的時間是包括[l,r]中比它們先出去的產品的完成時間的

      至於內部的順序問題 又到下一層函數解決了

      層層遞歸

 CODE

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 #define LY(p) freopen (p".in", "r", stdin); freopen (p".out", "w", stdout)
 9 #define LL long long
10 #define dbl double
11 #define lf long double
12 #ifdef WIN32
13 #define L_L "%I64d"
14 #else
15 #define L_L "%lld"
16 #endif
17 #define N 210
18 int n, t[N], d[N], st[N], sd[N];
19 LL f[N][N];
20 
21 int main()
22 {
23     scanf ("%d", &n);
24     for (int i = 1; i <= n; i++) {
25         scanf ("%d %d", &t[i], &d[i]);
26         st[i] = st[i - 1] + t[i];
27         sd[i] = sd[i - 1] + d[i];
28     }
29 
30     memset (f, 0x3f, sizeof (f));
31     for (int i = 1; i <= n; i++)
32         f[i][i] = d[i] * t[i], f[i][i - 1] = 0;
33     f[n + 1][n] = 0;
34 
35     for (int l = 1; l < n; l++)
36         for (int i = 1; i + l <= n; i++)
37         {
38             int j = i + l;
39             for (int k = i; k <= j; k++)
40                 f[i][j] = min
41                     (f[i][k - 1] + f[k + 1][j] + 1LL * (st[k - 1] - st[i - 1]) * (sd[j] - sd[k]) + 1LL * (st[j] - st[i - 1]) * d[k], f[i][j]);
42         }
43 
44     printf (L_L, f[1][n]);
45     return 0;
46 }
std View Code 非記搜
 1 #include<iostream>
 2 #include<cstdio>
 3 #define go(i,a,b) for(register int i=a;i<=b;i++)
 4 #define ll long long
 5 #define M 201
 6 #define inf 21000000000000
 7 using namespace std;
 8 ll read()
 9 {
10     int x=0,y=1;char c=getchar();
11     while(c<'0'||c>'9') {if(c=='-') y=-1;c=getchar();}
12     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
13     return x*y;
14 }
15 ll n,t[M],d[M],st[M],sd[M],f[M][M];
16 ll dfs(int l,int r)
17 {
18     if(l>r) return 0;
19     if(l==r) return t[l]*d[l];
20     if(f[l][r]) return f[l][r];
21     f[l][r]=inf;
22     go(i,l,r)
23         f[l][r]=min(f[l][r],dfs(l,i-1)+dfs(i+1,r)+(st[r]-st[l-1])*d[i]+(st[i-1]-st[l-1])*(sd[r]-sd[i]));
24     return f[l][r];
25 }
26 int main()
27 {
28     n=read();
29     go(i,1,n)
30     {
31         t[i]=read();st[i]=st[i-1]+t[i];
32         d[i]=read();sd[i]=sd[i-1]+d[i];
33     }
34     printf("%lld",dfs(1,n));
35     return 0;
36 }
dtt View Code 記搜
相關文章
相關標籤/搜索