動態規劃(DP) 之優先隊列最佳化 HDOJ 3401Trade

來源:互聯網
上載者:User

HDOJ 3401題目串連

 

 

告訴你 T 天裡,物品的買賣價格,和當天最多買賣數量,還有 T 天裡最多儲存物品數量,每一次買賣間隔時間必須大於 w+1

 

很容易想到DP【i】【j】表示,第i天結束的時候還儲存有j個物品時的最大獲利

 

初始化dp【i】【j】 = dp【i-1】【j】;

那麼狀態方程dp【i】【j】 = MAX(dp【k】【j】),其中k<= i - w - 1;

且有                 dp【i】【j】=MAX(dp【k】【z】 - (j - z) * buyValue【i】),其中,k<=i-w-1,z<j且 z>=j-maxBuy【i】;

還有                 dp【i】【j】=MAX(dp【k】【z】 + (z - j) * sellValue【i】),其中,k<=i-w-1,z>j且 z<=j  +  maxSell【i】;

 

所以會有i,j,z三層迴圈,而他們的範圍都是2000,所以有2000^3的複雜度,肯定逾時

 

這個時候我們可以用優先隊列來最佳化,使之少一層迴圈

 

z<j且 z>=j-maxBuy【i】的時候,dp【i】【j】= dp【k】【z】 - (j - z) * buyValue【i】= dp【k】【z】 + z  * buyValue【i】 -  j*buyValue【i】

 

可以發現dp【k】【z】 + z  * buyValue【i】部分只與z有關;

- j*buyValue【i】而後面的部分只與j有關,所有z都一樣;

 

所以我們需要的是式子前面這一部分的值越大越好,而z的範圍又隨著j的變化而變化,剛好是優先隊列的使用方式

 

 

這個題目有注意的地方

(1)就是k可以定為i-w-1,因為i-w-1之前的所有並沒有比i-w-1優,相反i-w-1這一天有可能比前面的優

(2)別忘了i可以從i-1天來

(3)最後的答案其實一定是剩餘0個物品的時候

 

My Code:

#include<stdio.h>
//#include<string.h>
//#include<algorithm>
#define CANNOT (-0x3fffffff)

#define MAX 2100

int dp[MAX][MAX];
int days[MAX][4];

int que[MAX], tail, front;
int where[MAX];

int t, maxp, w;

int Max(int a, int b)
{
 return a > b ? a : b;
}

int main()
{
 int i, j;
 int cases;
 int result;
 int xx;
 scanf("%d", &cases);
 while(cases --)
 {
  result = 0;
  scanf("%d%d%d", &t, &maxp, &w);
  for(i = 1; i <= t; i ++)
  {
   scanf("%d%d%d%d", &days[i][0], &days[i][1], &days[i][2], &days[i][3]);
  }
  for(i = 1; i <= t; i ++)
  {
   if(i <= w + 1)
   {
    for(j = 0; j <= maxp; j ++)
    {
     if(j <= days[i][2])
     {
      dp[i][j] = -j * days[i][0];
     }
     else
     {
      dp[i][j] = CANNOT;
     }
     if(i > 1)
      dp[i][j] = Max(dp[i][j], dp[i - 1][j]);
    }
   }
   else
   {
    for(j = 0; j <= maxp; j ++)
    { 
     dp[i][j] = dp[i - w - 1][j];
     dp[i][j] = Max(dp[i][j], dp[i - 1][j]);
    }
    tail = -1;
    front = 0;
    int temp = 0;
    for(j = 0; j <= maxp; j ++)
    {
     while(temp < j)
     {
      if(dp[i - w - 1][temp] == CANNOT)
      {
       temp ++;
       continue;
      }
      xx = dp[i - w - 1][temp] + temp * days[i][0];
      while(front <= tail)
      {
       if(xx >= que[tail])
        tail --;
       else
        break;
      }
      que[++ tail] = xx;
      where[tail] = temp;
      temp ++;
     }
     while(front <= tail && j - where[front] > days[i][2])
     {
      front ++;
     }
     if(front <= tail)
     dp[i][j] = Max(dp[i][j], que[front] - j * days[i][0]);
    }

    tail = -1;
    front = 0;
    temp = 0;
    for(j = 0; j <= maxp; j ++)
    {
     while(temp <= j + days[i][3] && temp <= maxp)
     {
      if(dp[i - w - 1][temp] == CANNOT || temp <= j)
      {
       temp ++;
       continue;
      }
      xx = dp[i - w - 1][temp] + temp * days[i][1];
      while(front <= tail)
      {
       if(xx >= que[tail])
        tail --;
       else
        break;
      }
      que[++ tail] = xx;
      where[tail] = temp;
      temp ++;
     }
     while(front <= tail && where[front] <= j)
     {
      front ++;
     }
     if(front <= tail)
     dp[i][j] = Max(dp[i][j], que[front] - j * days[i][1]);
    }
   }
  }
 // result = 0;
 // for(i = 0; i <= maxp; i ++)
 //  result = Max(result, dp[t][i]);
 // printf("%d\n", result);
  printf("%d\n", dp[t][0]);
 }
 return 0;
}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.