dp&遞推+題目練習(未完待續)

第一行——咕咕咕。

第二行——不吃早飯的後果是會餓,連續不吃早飯的後果是養成了到點兒就餓的生物鐘。別問,問就是在想中午吃點啥。啊啊啊懷念七月上旬醒來就有飯吃的日子qwq

第三行——昨天請了十分鐘的假,sj師哥很爽快(此處存疑)地答應了,然後下一句是

咱也不知道怎麼回事咱也不敢反駁.jpg

於是——

但是我真的不會dp啊qwq以前遇到這樣的題基本都是略過的呢(委屈巴巴.jpg),於是您可以看到一個瘋狂想遞推公式就是想不出來,一上午做不了一個dp的人欲哭無淚。

但剛好趁這個機會練習dp了,嗯嗯迎難而上(滑稽.jpg)。

sj師哥是個好隊長(瘋狂點頭.jpg)

1.SDNU1044

這道題的坑點是“花在花瓶中的先後順序必須與給定順序相同”,也就是說,當第j個瓶放了第i朵fafa後,第i+1朵fafa就只能放在第j+1及其之後的瓶了。

遞推公式:

for(int i = 1; i <= n; ++i)//花
  for(int j = 1; j <= m; ++j)//瓶
  {
      if(i > j)
          continue;
      else
          dp[i][j] = max(dp[i-1][j-1]+a[i][j],dp[i][j-1]);
  }

2.HDU1087

思路:用dp[i]存最後一步到dp[i]時候的最大值,外層是初始化爲一步的值,內層是判斷前面有沒有可以跳的點(滿足當前點大於上一個可跳的點),更新dp的值。

沒發現有啥坑。

記得最後再跑一次循環找max。

遞推公式:

for(int i = 0; i < n; ++i)
  {
      dp[i] = a[i];
      for(int j = 0; j < i; ++j)
      {
          if(a[i] > a[j])
              dp[i] = max(dp[i],dp[j]+a[i]);
      }
   }

SDNU1330這個跟2一樣。

3.HDU1114

思路:用dp存放滿i容量時最少的錢數,枚舉錢的cost和value找最小

遞推公式:

for(int i = 1; i <= volume; ++i)
{
    for(int j = 0; j < n; ++j)
       {
          if(i-c[j] >= 0)
           {
              dp[i] = min(dp[i],dp[i-c[j]]+v[j]);
           }
       }
}

4.SDNU1038

思路:只能向右向下,所以當前點可由上一行的同列或同一行的前一列遞推過來。

遞推公式:

for(int i = 1; i <= n; ++i)
{
    for(int j = 1; j <= n; ++j)
    {
        dp[i][j] = max(dp[i-1][j],dp[i][j-1])+tu[i][j];
    }
}

5.牛客暑期多校第一場E.ABBA

思路:1.用dp[i][j]表示到有i個Aj個B的時候的方案數

2.dp[i][j]可以由dp[i-1][j]和dp[i][j-1]得到

3.利用貪心的策略,前n個A一定爲AB的A,前m個B一定爲BA的B,便於其組成AB和BA

4.i個A的時候,只要是前面的A小於n個或者多出來的A比前面的B少,就放A。用min(m,j)是因爲最多前面放m個B,當i爲n時且前面沒有B時就不能再放A了

5.j個B時同理,組成的BA小於m或者前面的B比A少時就放B

下附狀態轉移方程

dp[0][0] = 1;
for(int i = 0; i <= n+m; ++i)
    for(int j = 0; j <= m+n; ++j)
    {
        if(i < n || (i-n) < min(m,j))
            dp[i+1][j] = (dp[i+1][j] + dp[i][j])%mod;
        if(j < m || (j-m) < min(n,i))
            dp[i][j+1] = (dp[i][j+1] + dp[i][j])%mod;
    }

歡迎指出錯誤qwq

dp殺我!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章