UVA 10465 Homer Simpson(完全背包: 二維目標條件),10465homer

來源:互聯網
上載者:User

UVA 10465 Homer Simpson(完全背包: 二維目標條件),10465homer

UVA 10465 Homer Simpson(完全背包: 二維目標條件)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1406

題意:

       有兩種漢堡包(漢堡數量無限多),第一種吃一個需要花n分鐘,第二種吃一個需要花m分鐘. 現在你有t分鐘的時間, 問你最少浪費幾分鐘不能吃漢堡(你每次要麼完整的吃完一個漢堡,要麼不吃). 當吃漢堡花費的時間達到最大時, 問你最多能吃幾個漢堡?

分析:

       本題的限制條件是: 總時間<=t分鐘.

       本題的目標條件是: 總時間盡量大, 如果時間相同的情況下漢堡數目越多越好.

       二維(甚至多維)目標條件有兩種方法可以做.

       第一種方法是:先用完全背包求出最大時間tmax, 然後再用一次完全背包求出吃漢堡的時間正好等於最大時間tmax下, 最多能吃幾個漢堡.

       首先用完全背包求出最大時間tmax. 令dp[i][j]==x表示當決策完前i個漢堡後, 總時間不超過j分鐘時最多能花x分鐘. 那麼有下面遞推公式:

       dp[i][j] = max( dp[i-1][j] , dp[i][j-time[i]]+time[i] )

       前者表示一個i 漢堡都不選,後者表示至少選1個i漢堡.

初始化為dp全0. 最終tmax=dp[n][t].

       然後我們求在花費時間正好tmax的情況下的最大漢堡數. 令dp[i][j]==x 表示決策完全i個物品後, 時間正好為j分鐘時的最大漢堡數目為x個. 那麼有下面遞推公式:

       dp[i][j] = max( dp[i-1][j] , dp[i][j-time[i]]+1)

       前者表示一個i 漢堡都不選,後者表示至少選1個i漢堡.

初始化為dp全-1.且dp[0][0]=0.

       最終最大漢堡數=dp[n][tmax].

       第二種方法是:

       UVA12563題目一樣的思想:

       http://blog.csdn.net/u013480600/article/details/40376143

       一般我們做的背包問題都是問你<=t的時間內, 如何選擇哪些漢堡(在不超過總時間的前提下)能使得吃的時間最長或 吃的漢堡最多. 但是本題需要同時考慮兩個最優條件, 那麼該怎麼做呢?

       我們令dp[i][j]==x 表示當決策完全前i個物品後(選或不選), 吃漢堡花的時間<=j時, 所得到的最優狀態為x. (這裡的x就不是平時我們所說的最長時間或最多歌曲數目了)

       怎麼理解最優狀態為x這個事實呢? 假設有兩種選擇前i個漢堡的方法能使得決策完前i個物品且總時間長度<=j時的狀態分別為x1 和x2.

       那麼如果x1狀態的吃漢堡時間> x2狀態的吃漢堡時間, 那麼明顯x1狀態更優. 所以dp[i][j]應==x1.

       如果x1狀態的吃漢堡時間與x2的相等, 但是x2狀態的吃漢堡數目 > x1狀態的吃漢堡數目, 那麼此時x2狀態更優. 所以dp[i][j]應==x2.

       經過上面的分析,我們可以用一個(具有吃漢堡時間和吃漢堡數目雙屬性的)結構體來表示一個狀態. 且可以得到下面狀態轉移公式:

       dp[i][j] = 最優(dp[i-1][j] , 在dp[i-1][j-time[i]]的基礎上選擇第i個漢堡後得到的新狀態tmp )

       所有dp初始化為0即可. 最終我們所求為dp[n][t]

       程式實現用的滾動數組,所以dp只有[j]這一維.

AC代碼1:用方法1兩次DP做的

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=10000+5;int n,m,t;//對應題意的含義int time[5];//吃第i種漢堡所花時間int dp[maxn];int main(){    while(scanf("%d%d%d",&time[1],&time[2],&t)==3)    {        //遞推最大時間        memset(dp,0,sizeof(dp));        for(int i=1;i<=2;i++)        {            for(int j=time[i];j<=t;j++)                dp[j] = max(dp[j], dp[j-time[i]]+time[i]);        }        int tmax=dp[t];        //遞推最大漢堡數目        memset(dp,-1,sizeof(dp));        dp[0]=0;        for(int i=1;i<=2;i++)        {            for(int j=time[i];j<=tmax;j++)if(dp[j-time[i]]!=-1)                dp[j] = max(dp[j], dp[j-time[i]]+1);        }        //輸出結果        printf("%d",dp[tmax]);        if(t>tmax) printf(" %d",t-tmax);        printf("\n");    }    return 0;}

AC代碼2:用方法2一次DP做的

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=10000+5;int n,m,t;  //對應題意的含義int time[5];//吃第i種漢堡所花時間struct Node //每個狀態{    int time;//吃漢堡時間    int num; //吃漢堡數目    bool operator<(const Node &rhs)const    {        return time<rhs.time || (time==rhs.time && num<rhs.num);    }}dp[maxn];int main(){    while(scanf("%d%d%d",&time[1],&time[2],&t)==3)    {        //初始化        memset(dp,0,sizeof(dp));        //遞推        for(int i=1;i<=2;i++)        {            for(int j=time[i];j<=t;j++)            {                Node tmp=dp[j-time[i]];                tmp.time += time[i];                tmp.num++;                if(dp[j]<tmp) dp[j]=tmp;            }        }        //輸出結果        printf("%d",dp[t].num);        if(dp[t].time<t) printf(" %d",t-dp[t].time);        printf("\n");    }    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.