zoukankan      html  css  js  c++  java
  • HDU 3535 AreYouBusy(分组DP)

    HDU 3535  AreYouBusy

    题解:dp[i][j]表示的是在第i组剩余时间为j时的快乐值,我们需要对每一组工作进行一次DP。

    第一类:即s==0时,表示该组中工作必须要选且至少选一项。为了保证不出现不选的现象,我们应该把DP数组初始化为负无穷。状态转移方程为: dp[i][k]=max(dp[i][k],max(dp[i-1][k-c[j]]+val[j],dp[i][k-c[j]]+val[j])); dp[i][k]表示不选该组中的第j个工作,dp[i-1][k-c[j]]+val[j]表示选第j项工作且是第一次在本组中选。dp[i][k-c[j]]+val[j])表示选第j项工作且不是第一次在本组中选。

    第二类:即s==1时,最多选一项,即要么不选,一旦选,只能是第一次选。状态转移方程为:  dp[i][k]=max(dp[i][k],dp[i-1][k-c[j]]+val[j]) 由于要保证得到全局最优解,所以在该组DP开始以前,应该将上一组的DP结果先复制到这一组的dp[i]数组里,因为这一组的数据是在上一组数据的基础上进行更新的。

    第三类:即s==2时,任意选,即不论选不选,选几次都可以。状态转移方程与第一类一致,不同的在于第三类对dp的初始化为上一组的值,而不是初始化为负无穷。

    最近又理解了一下:至少选一个时,将当前组的dp全部赋值为-inf,以保证一定能选,最多选一个和随便选时,将上一组的dp值复制到当前组,表示的意思是当前组一个都不选,最多选一个,需要由上一组的值来更新,即

    选就一定是在本组第一次选:dp[i][k]=max(dp[i][k],dp[i-1][k-c[j]]+val[j]) 而随便选则为一个简单的01背包,可写成dp[i][k]=max(dp[i][k],dp[i][k-c[j]]+val[j])。 新代码在下面。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define inf -0x3f3f3f3f
     6 using namespace std;
     7 const int maxn=110;
     8  
     9 int n,t;
    10 int dp[maxn][maxn];
    11 int m,s,c[maxn],val[maxn];
    12 int main()
    13 {
    14     while(~scanf("%d%d",&n,&t))
    15     {
    16         memset(dp,0,sizeof(dp));
    17         for(int i=1;i<=n;i++)
    18         {
    19             scanf("%d%d",&m,&s);
    20             for(int j=1;j<=m;j++)
    21                 scanf("%d%d",&c[j],&val[j]);
    22             if(s==0)
    23             {
    24                 for(int j=0;j<=t;j++)
    25                     dp[i][j]=inf;
    26                 for(int j=1;j<=m;j++)
    27                 {
    28                     for(int k=t;k>=c[j];k--)
    29                     {
    30                         dp[i][k]=max(dp[i][k],max(dp[i-1][k-c[j]]+val[j],dp[i][k-c[j]]+val[j]));
    31                     }
    32                 }
    33             }
    34             else if(s==1)
    35             {
    36                 for(int j=0;j<=t;j++)
    37                 {
    38                     dp[i][j]=dp[i-1][j];
    39                 }
    40                 for(int j=1;j<=m;j++)
    41                 {
    42                     for(int k=t;k>=c[j];k--)
    43                     {
    44                         dp[i][k]=max(dp[i][k],dp[i-1][k-c[j]]+val[j]);
    45                     }
    46                 }
    47             }
    48             else if(s==2)
    49             {
    50                 for(int j=0;j<=t;j++)
    51                 {
    52                     dp[i][j]=dp[i-1][j];
    53                 }
    54                 for(int j=1;j<=m;j++)
    55                 {
    56                     for(int k=t;k>=c[j];k--)
    57                     {
    58                         dp[i][k]=max(dp[i][k],max(dp[i-1][k-c[j]]+val[j],dp[i][k-c[j]]+val[j]));
    59                     }
    60                 }
    61             }
    62     
    63         }
    64         dp[n][t]=max(dp[n][t],-1);
    65         printf("%d
    ",dp[n][t]);
    66     }
    67 return 0;
    68 }
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<stack>
     5 #include<algorithm>
     6 #define inf 0x3f3f3f3f
     7 using namespace std;
     8 const int maxn=200100;
     9 int dp[110][110];
    10 int c[110],val[110];
    11 int n,t;
    12 int maxx(int a,int b,int c)
    13 {
    14     int t=a>b?a:b;
    15     return t>c?t:c;
    16 }
    17 int main()
    18 {
    19     while(~scanf("%d%d",&n,&t))
    20     {
    21         memset(dp,0,sizeof(dp));
    22         int type,m;
    23         for(int i=1;i<=n;i++)
    24         {
    25             scanf("%d%d",&m,&type);
    26             for(int j=1;j<=m;j++)
    27             {
    28                 scanf("%d%d",&c[j],&val[j]);
    29             }
    30             if(type==0)
    31             {
    32                 for(int j=0;j<=t;j++)
    33                     dp[i][j]=-inf;
    34                 for(int j=1;j<=m;j++)
    35                 {
    36                     for(int k=t;k>=c[j];k--)
    37                     {
    38                         dp[i][k]=maxx(dp[i][k],dp[i-1][k-c[j]]+val[j],dp[i][k-c[j]]+val[j]);
    39                     }
    40                 }
    41 
    42             }
    43             else if(type==1)
    44             {
    45                 for(int j=0;j<=t;j++)
    46                     dp[i][j]=dp[i-1][j];
    47                 for(int j=1;j<=m;j++)
    48                 {
    49                     for(int k=t;k>=c[j];k--)
    50                     {
    51                         dp[i][k]=max(dp[i][k],dp[i-1][k-c[j]]+val[j]);
    52                     }
    53                 }
    54             }
    55             else
    56             {
    57                 for(int j=0;j<=t;j++)
    58                     dp[i][j]=dp[i-1][j];
    59                 for(int j=1;j<=m;j++)
    60                 {
    61                     for(int k=t;k>=c[j];k--)
    62                     {
    63                         dp[i][k]=max(dp[i][k],dp[i][k-c[j]]+val[j]);
    64                     }
    65                 }
    66             }
    67         }
    68        if(dp[n][t]>0)
    69             cout<<dp[n][t]<<endl;
    70        else
    71             cout<<-1<<endl;
    72     }
    73 return 0;
    74 }
  • 相关阅读:
    平衡树(Splay):Splaytree POJ 3580 SuperMemo
    数据结构:(平衡树,链表)BZOJ 1588[HNOI2002]营业额统计
    主席树:HDU 4417 Super Mario
    主席树:POJ2104 K-th Number (主席树模板题)
    后缀数组模板
    后缀数组:HDU1043 Longest Common Substring
    后缀数组:SPOJ SUBST1
    关于PHP程序员解决问题的能力
    现在写 PHP,你应该知道这些
    PHP 7 的几个新特性
  • 原文地址:https://www.cnblogs.com/1013star/p/9489344.html
Copyright © 2011-2022 走看看