2020.2.8鐵一寒假收官賽題解

2020.2.8鐵一寒假收官賽題解

  • 題目均爲原題或改編,已得到題主許可
  • 出題人:Memoryヾノ戰心
  • BigYellowDog選手寫了份題解,得到出題人許可

T1

  • 這道題是一道很經典的簡單dp模型(不會dp的可以先去自學簡單入個門

  • 有O(n方)或者O(nlogn)的做法,數據範圍n最大不超200,顯然O(n方)算法足矣

  • 題目要求最少抽出幾本書,可以轉化爲求最長“舒服樣子”序列的元素個數w。答案即爲:n-w

  • 具體思路就是定義數組dp1[], dp2[]

  • dp1[i]表示從左到右看,以第i個位置爲結尾,所能構成的 最長舒服序列 的 書數量

  • dp2[i]表示從右到左看,以第i個位置爲結尾,所能構成的 最長舒服序列 的 書數量

  • 轉移方法如下:(下面是dp1[]的轉移代碼,dp2[]同理)

    for(int i=2;i<=n;i++) //枚舉i的位置
      for(int j=1;j<i;j++) //枚舉j的位置,顯然i的上一個人必須在他左邊,所以不能超過i
          if(a[i]>a[j]) //必須要i的高度>j的高度才能接上去
              dp1[i]=max(dp1[j]+1,dp1[i]); //如果執行到這裏就說明i位置可以接到"以j位置爲結尾的序列"上,那麼"接"和"不接"倆選擇,哪個好就選擇哪個
  • 如何算答案?只需從1-n枚舉每個位置,每個位置的最優答案是dp1[i]+dp2[i]-1(減1是因爲位置i統計了兩次)。那麼最終答案就是(n-取n個位置的最優答案中的最大值)。

  • 感覺自己不太擅長揣測沒學過dp同學的心理,所以這篇如寫得不明白,還請指出。

T2

  • 算法是搜索+完全揹包dp。(不會的先去自學簡單入個門
  • 顯然數字1卡片必須選,那麼下一張選什麼呢?
  • 通過觀察了幾組小數據我發現每次要選的數字範圍爲[上一個選的數+1,上一次能組成的最大面值+1]

  • 我不會嚴謹地證明這個結論,但並不影響做題

  • 得出每次選的數範圍後,就可以搜索了。搜索思路即每次從範圍中選一個數,然後與前面選的數合在一起算出一個最大面值。如果此時的最大面值>記錄的最大面值,就將記錄的最大面值更新爲此時的最大面值。

  • 這樣做估計有30分(沒試過),會超時。問題出在了計算最大面值這一步上,可以用揹包來優化。

  • 揹包思路是定義dp[],dp[i]表示湊出i這個面值最少需要的卡片數。用完全揹包模板算出dp數組,然後從1枚舉到一個人爲設的很大的數,如果dp[i]>n了,那麼此時的最大面值就是i-1

  • 此題完全揹包代碼如下:

  • //雖說是模板,但建議要去找資料弄懂爲什麼
    memset(dp,0x3f,sizeof(dp)),dp[0]=0;
    for(int i=1;i<=fro;i++)
        for(int j=c[i];j<=c[i]*n;j++)
            dp[j]=min(dp[j],dp[j-c[i]]+1);
    for(int i=1;i<=c[fro]*n;i++)
        if(dp[i]>n) return i-1;

T3

  • 算法是邏輯分析+貪心
  • 我先簡化了題意:
    • n條序列,每條序列不嚴格遞增,花1h可以取到其中一個序列的頭,對於每個序列必須按順序取。
    • 問用n個小時最多取到的最大總價值?
  • 於是當時我就畫圖+手玩得出結論:答案即分別將n個小時用到每一條序列,取最優值。
  • 這很好理解,要將每個小時發揮最大的價值。顯然是選擇用到頭的金幣最大的序列。那麼又因爲序列越往後越大,所以在原來的江山上繼續奮鬥肯定比重零開始做人更優對吧
  • 嚴謹的證明不會
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章