hdu 3535 AreYouBusy(分组背包的变形---各种分组背包)

来源:互联网 发布:php网络验证系统源码 编辑:程序博客网 时间:2024/05/22 01:53

题目分析:0代表每组内的job至少取一件;1代表最多取一件;2代表可以自由取,就相当于对这一组内的job实行01背包......

注意:  1. One job can be done only once.开始没注意到这句话,还以为每组内的每个job可以做多次....囧,,,

             2.这个题花了我一天多的时间,最后看别人的解题报告才过的,,,,

             3.应该先做  hdu  3033的,这个相对于这个简单一些

             4.这个貌似不能压缩空间.....我开始压缩空间做的,一直错,样例都过不了


/*该题要用分组背包做,这里就是要怎样处理0必须选,1最多选一个,2任意选的问题;这里我们就开个二维数组;f[i][j],i表示第组,j表示时间;当该组为0时,我们在该组的选择可以来自上一组的结果,也可以来自该组的结果;如果为1那么结果只能依赖上一组的结果,如果依赖本组那么就会造成该组会多选;为2是那就是一个01背包;*/#include<iostream>#include<cstdio>#include<algorithm>#include<memory.h>using namespace std;struct node{    int c,g;}arr[1000];int dp[1000][1000];int main(){int n,t,m,s;while(scanf("%d %d",&n,&t)!=EOF){memset(dp,-1,sizeof(dp));memset(dp[0],0,sizeof(dp[0]));for(int x=1;x<=n;x++){    scanf("%d %d",&m,&s);   // memset(dp,0,sizeof(dp));****不要再犯这样的低级错误    for(int i=1;i<=m;i++)scanf("%d %d",&arr[i].c,&arr[i].g);   if(s==0)//每组内.至少取一件,我们在该组的选择可以来自上一组的结果.也可以来自该组的结果;{ for(int i=1;i<=m;i++)       // for(int i=0;i<=t;i++) for(int k=t;k>=arr[i].c;k--)  // for(int k=1;k<=m;k++) { if(dp[x][k-arr[i].c]!=-1) dp[x][k]=max(dp[x][k],dp[x][k-arr[i].c]+arr[i].g);//如果dp[i][k-arr[i].c]存在,则表示i组已经取过了,就相当与在去过的基础上再取,即,至少一个 if(dp[x-1][k-arr[i].c]!=-1)   dp[x][k]=max(dp[x][k],dp[x-1][k-arr[i].c]+arr[i].g);//确保取一个 }}else if(s==1)//每组至多取一件,就是分组背包的原形.{//只能依赖上一组的结果,如果依赖本组那么就会造成该组会多选               for(int k=1;k<=m;k++)//for(int i=t;i>=0;i--)   for(int i=t;i>=0;i--)//for(int k=1;k<=m;k++)   {   dp[x][i]=max(dp[x][i],dp[x-1][i]);   if(i>=arr[k].c && dp[x-1][i-arr[k].c]!=-1)       dp[x][i]=max(dp[x][i],dp[x-1][i-arr[k].c]+arr[k].g);   }}else//每组内的,可以取任意件,相对于对每一组内的每一件,进行01背包{for(int k=0;k<=t;k++)dp[x][k]=dp[x-1][k];               for(int k=1;k<=m;k++)   for(int i=t;i>=arr[k].c;i--)   if(dp[x][i-arr[k].c]!=-1)     dp[x][i]=max(dp[x][i],dp[x][i-arr[k].c]+arr[k].g);}   }/*if(dp[n][t]==0)printf("-1\n");else*/     printf("%d\n",dp[n][t]);}system("pause");return 0;}/***************************//有错,压缩空间#include<iostream>#include<cstdio>#include<algorithm>#include<memory.h>using namespace std;struct node{    int c,g;}arr[1000];int dp[1000000];int main(){int n,t,m,s;while(scanf("%d %d",&n,&t)!=EOF){memset(dp,0,sizeof(dp));for(int x=1;x<=n;x++){    scanf("%d %d",&m,&s);   // memset(dp,0,sizeof(dp));****不要再犯这样的低级错误    for(int i=1;i<=m;i++)scanf("%d %d",&arr[i].c,&arr[i].g);   if(s==0)//每组内.至少取一件,我们在该组的选择可以来自上一组的结果.也可以来自该组的结果;{   for(int i=1;i<=m;i++)       // for(int i=0;i<=t;i++)   for(int k=t;k>=arr[i].c;k--)  // for(int k=1;k<=m;k++)   dp[k]=max(dp[k],dp[k-arr[i].c]+arr[i].g);}else if(s==1)//每组至多去一件,就是分组背包的原形.{//只能依赖上一组的结果,如果依赖本组那么就会造成该组会多选               for(int i=t;i>=0;i--)   for(int k=1;k<=m;k++)   if(i-arr[k].c>=0)       dp[i]=max(dp[i],dp[i-arr[k].c]+arr[k].g);}else//每组内的,可以取任意件,相对于对每一组内的每一件,进行01背包{               for(int k=1;k<=m;k++)   for(int i=t;i>=arr[k].c;i--)   dp[i]=max(dp[i],dp[i-arr[k].c]+arr[k].g);}   }if(dp[t]==0)printf("-1\n");else        printf("%d\n",dp[t]);}system("pause");return 0;}*//***************比人的代码个细节不懂,谁知道的话帮个忙,留个言~三种背包,每组至少、至多取一个或随意取多少注释在代码中?#include<cstdio>#include<cstring>int dp[110][110];int max(int a,int b){    return a>b?a:b;}int main(){    int n,T,i,j,k,m,s,w,v;    while(scanf("%d%d",&n,&T)!=EOF)    {        memset(dp,0,sizeof(dp));        for(i=1;i<=n;i++)        {            scanf("%d%d",&m,&s);            if(s==0)//至少选一个            {                for(j=0;j<=T;j++)                    dp[i][j]=-1;//保证下面会有一个被选中                for(j=1;j<=m;j++)                {                    scanf("%d%d",&w,&v);                    for(k=T;k>=w;k--)                    {                        //下面这两句话为什么一换就错啊,不懂了。。。。                        if(dp[i][k-w]!=-1)     dp[i][k]=max(dp[i][k],dp[i][k-w]+v);//如果dp[i][k-w]存在,则表示i组已经取过了,就相当与在去过的基础上再取,即,至少一个                        if(dp[i-1][k-w]!=-1)        dp[i][k]=max(dp[i-1][k-w]+v,dp[i][k]);//保证一定取一个                    }                }            }            if(s==1)//至多选一个            {                for(j=0;j<=T;j++)                    dp[i][j]=dp[i-1][j];                for(j=1;j<=m;j++)                {                    scanf("%d%d",&w,&v);                    for(k=T;k>=w;k--)                    {                        if(dp[i-1][k-w]!=-1)                            dp[i][k]=max(dp[i][k],dp[i-1][k-w]+v);                    }                }            }            if(s==2)//随意选            {                for(j=0;j<=T;j++)                    dp[i][j]=dp[i-1][j];                for(j=1;j<=m;j++)                {                    scanf("%d%d",&w,&v);                    for(k=T;k>=w;k--)                    {                        if(dp[i][k-w]!=-1)                            dp[i][k]=max(dp[i][k],dp[i][k-w]+v);                    }                }            }        }        int ans=-1;        for(i=0;i<=T;i++)        {            if(dp[n][i]>ans)                ans=dp[n][i];        }        printf("%d\n",ans);    }    return 0;}   View Code 分类: 动态规划标签: 背包绿色通道:好文要顶关注我收藏该文与我联系 Because Of You关注 - 1粉丝 - 5+加关注0 0(请您对文章做出评价)« 博主前一篇:关于分组背包» 博主后一篇:zstu 1032 拆分物品 再01背包posted @ 2011-11-19 15:00 Because Of You Views(48) Comments(0) Edit 收藏*//*该题要用分组背包做,这里就是要怎样处理0必须选,1最多选一个,2任意选的问题;这里我们就开个二维数组;f[i][j],i表示第组,j表示时间;当该组为0时,我们在该组的选择可以来自上一组的结果,也可以来自该组的结果;如果为1那么结果只能依赖上一组的结果,如果依赖本组那么就会造成该组会多选;为2是那就是一个01背包;*//*http://www.haogongju.net/art/1343345#include<cstdio>#include<iostream>#include<cstring>using namespace std;class node{    public:    int cost,happy;};class Node{   public:   node t[124];   int type,N; };Node T[124];int Max( int a, int b ){    return a > b ? a : b; }int DP( int n , int time ){    int f[124][124];     memset( f , -1 , sizeof( f ) );    memset( f[0] , 0 ,sizeof(f[0]) );    for( int i = 1 ; i <= n ; i ++ )   {       switch( T[i].type )       {          case 0: //至少取一件,即依赖上组,一依赖本组          for( int j = 0 ; j < T[i].N; j++ )             for( int k = time ; k >= T[i].t[j].cost ; k-- )             {                if( f[i][k-T[i].t[j].cost]!=-1 )                    f[i][k] = Max(f[i][k],f[i][k-T[i].t[j].cost] + T[i].t[j].happy);                if( f[i-1][k-T[i].t[j].cost]!=-1 )                    f[i][k] = Max(f[i][k],f[i-1][k-T[i].t[j].cost] + T[i].t[j].happy);             }             break;            case 1://至多取一件,只依赖本组            for( int j = 0 ; j < T[i].N; j++ )               for( int k = time ; k >= 0 ; k-- )               {                   f[i][k] = Max(f[i-1][k],f[i][k]); //????                   if( k-T[i].t[j].cost>=0&&f[i-1][k-T[i].t[j].cost] != -1 )                      f[i][k] = Max( f[i][k],f[i-1][k-T[i].t[j].cost] + T[i].t[j].happy );               }               break;           case 2://任意取,01背包           for( int j = 0 ; j <= time ; j++)           {              f[i][j] = f[i-1][j];           }           for( int j = 0 ; j < T[i].N; j++ )   for( int k = time ; k >0; k-- )               {                 if( k-T[i].t[j].cost>=0&&f[i][k-T[i].t[j].cost]!=-1 )                      f[i][k] = Max(f[i][k], f[i][k-T[i].t[j].cost] + T[i].t[j].happy);              }             break;       } //switch     }     return f[n][time];}int main( ){int n , m , time, type;while( scanf( "%d%d",&n , &time )==2 ){for( int i = 1 ; i <= n ; i++ ){scanf( "%d%d",&T[i].N, &T[i].type );for( int j = 0 ; j < T[i].N ; j++ ){scanf( "%d%d",&T[i].t[j].cost , &T[i].t[j].happy );}}printf("%d\n", DP( n , time )); }return 0; }*/


原创粉丝点击