背包問題-Bone Collector II

來源:互聯網
上載者:User

這是一道求背包問題第k次大解。思路稍有點變法,就是在遞迴的過程中,分別用兩個數組記錄兩種狀態(選擇或不選擇),並且只要記錄前k次。在這兩個數組中都是前k次可能的最優解。所以我們只要把這兩個數組做比較,一直排到k就行了,另外,對於遞迴問題,我們只要抓住某個狀態的前後關係,把複雜問題簡單化,不必去糾結全過程的狀態,應為程式在運行時,遞迴過程是用堆棧實現的,其變化複雜,沒必要每步弄懂。重點在於抓住前後規律和設計思路就可以了。

#include<stdio.h>#include<string.h>int dp[1001][50],wi[100],di[100];    int n,m,k; void BK()  {    int a[50],b[50];           //用於記錄當體積為j時,它的價值量。     int i,j,h;    int x,y,z;    for(i=0;i<n;i++)     for(j=m;j>=wi[i];j--)     {       for(h=1;h<=k;h++)          //把前k個一次比較排序,不必要全部排完。          {          a[h]=dp[j-wi[i]][h]+di[i];   //選擇兩次狀態,應為它的優解,只可能在這兩者選擇。           b[h]=dp[j][h];               //要麼選擇一個,要麼不選擇。           }             x=y=z=1,a[h]=b[h]=-1;              //從兩個數組中把前k的值排序,此時h>K,就不必管他了,令它為-1是應為         while(z<=k&&(a[x]!=-1||b[y]!=-1))  // 在選的時候,以保證x,y不會超出k範圍。          {                                //這個迴圈就是從前k個裡面選出最優解(降序)。             if(a[x]>b[y])              dp[j][z]=a[x++];            else              dp[j][z]=b[y++];            if(dp[j][z]!=dp[j][z-1])                z++;         }       }     printf("%d\n",dp[m][k]);}                       int main()  {       int t,i;    scanf("%d",&t);    while(t--)     {      scanf("%d%d%d",&n,&m,&k);      for(i=0;i<n;i++)       scanf("%d",&di[i]);       for(i=0;i<n;i++)       scanf("%d",&wi[i]);       memset(dp,0,sizeof(dp));       BK();       }       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.