日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AreYouBusy

發布時間:2023/12/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AreYouBusy 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

AreYouBusy

題意:

給你n個工作集合,給你T的時間去做它們。給你m和s,說明這個工作集合有m件事可以做,它們是s類的工作集合(s=0,1,2,s=0說明這m件事中最少得做一件,s=1說明這m件事中最多只能做一件,s=2說明這m件事你可以做也可以不做)。再給你ci和gi代表你做這件事要用ci的時間,能獲得gi的快樂值。求在T的時間內你能獲得的最大快樂值。

題解:

我們設dp[i][j]表示處理完前i組工作集,所用時間小于j的快樂值
dp[i]表示的是第i組的結果,每組相對獨立,
所以對于每一組情況,我們就可以將dp看作是一維數組,只考慮第二維j,考慮第一維僅為需要繼承狀態時
我們分析三種集合:

  • 至少選一項。在開始時dp初始化為負無窮,這樣是為了保證不會出現都不不選的情況,負無窮相當于這個情況不合法即未選
    轉移方程:
  • dp[i][j]=max(dp[i][j],max(dp[i][j-w[x]]+p[x],dp[i-1][j-w[x]]+p[x]));

    dp[i][j]表示不選這個工作
    dp[i][j-w[x]]+p[x]:表示選擇當前工作,且不是第一次取(為什么這個能保證不是第一次取?因為我們一開始將dp[i][…]賦值為負無窮,如果dp[i][j-w[x]]沒被選過就還是負無窮,則整個式子取最大就跟他無關,如果被選過,則dp[i][j-w[x]]為正數)
    dp[i-1][j-w[x]]+p[x]:第一次在本組中選物品,由于dp初始化為負無窮,所以狀態的轉移只能從上一組的結果中得知,這樣可以保證得到全局最優解
    這樣,當有一組無法完成時,最后的答案就是負無窮

  • 最多選一項,要么不選,要么就是第一次選
    為了保證全局最優解,dp[i][j]繼承上一組的狀態
    第一次選的話,和第一種集合的情況一樣
  • dp[i][j]=max(dp[i][j],dp[i-1][j-w[x]]+p[x]);
  • 任意選就是01背包
    為了保證全局最優解,dp[i][j]繼承上一組的狀態
  • dp[i][j]=max(dp[i][j],dp[i][j-w[x]]+p[x]);

    這里的dp是被壓縮了一維的,這里的dp[][j]中的j等于01背包的一維數組dp[j],
    dp[i][]中的i只是表示第i組的情況

    代碼:

    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm>using namespace std;const int INF=0x3f3f3f3f;int n,m,sum; int w[110],p[110]; int dp[110][110];int main(){//freopen("input.txt","r",stdin);while(~scanf("%d%d",&n,&sum)){memset(dp,0,sizeof(dp));int i,j,k,g;for(i=1;i<=n;i++){scanf("%d%d",&m,&g);for(k=1;k<=m;k++)scanf("%d%d",&w[k],&p[k]);if(g==0){//至少選一個 for(j=0;j<=sum;j++) //當前組初始化dp[i][j]=-INF;for(k=1;k<=m;k++)for(j=sum;j>=w[k];j--)dp[i][j]=max(dp[i][j],max(dp[i][j-w[k]]+p[k],dp[i-1][j-w[k]]+p[k]));}else if(g==1){//最多選一個 for(j=0;j<=sum;j++) //當前組初始化dp[i][j]=dp[i-1][j];for(k=1;k<=m;k++)for(j=sum;j>=w[k];j--)dp[i][j]=max(dp[i][j],dp[i-1][j-w[k]]+p[k]); //dp[i-1][j-w[k]]//j-w[k]<j}else if(g==2){//自由選擇 for(j=0;j<=sum;j++) //當前組初始化dp[i][j]=dp[i-1][j];for(k=1;k<=m;k++)for(j=sum;j>=w[k];j--)dp[i][j]=max(dp[i][j],dp[i][j-w[k]]+p[k]);}}dp[n][sum]=max(dp[n][sum],-1); //沒有完成任務的值都為負的,做輸出調整,輸出-1printf("%d\n",dp[n][sum]);}return 0; }

    總結

    以上是生活随笔為你收集整理的AreYouBusy的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。