• hdu3033 I love sneakers! && hdu3535 AreYouBusy (组合背包)


    hdu3033 题目要求与普通的组合背包(每组至多选一个)有所区别,而本题目的话,每组至少选一个,

    那么如何保证每组至少选一个呢,问题就在初始化的问题还有状态转移的问题了

    if(f[i][l-br[i].b[j]]!=-1 && f[i][l]<f[i][l-br[i].b[j]]+br[i].c[j]) //从当前组再多选一个
                            f[i][l]=f[i][l-br[i].b[j]]+br[i].c[j];

     if(f[i-1][l-br[i].b[j]]!=-1 && f[i][l]<f[i-1][l-br[i].b[j]]+br[i].c[j]) //在上一组的状态下,选当前组的一个
                            f[i][l]=f[i-1][l-br[i].b[j]]+br[i].c[j];

    就上面这段关键的代码

     在某一状态存在的情况下(不等于-1),找出三种状态中最大的,赋值给f[i][j] .由于开始时所有f[i][j](i!=0)都为-1,所以更新时一定会从f[0][]开始,而此时就可保证当i=1时,f[i][j]中所有值不为-1的状态一定装了品牌1的某个物品。而当i>1时,
           要想得到 最初 的f[i][j],一定是从已经放有前i-1个品牌的某个状态得到的,而更新最初 的f[i][j] 也一定会用到i品牌的某
           个产品(都可由状态转移方程可知)。
           总之,保证每一类品牌 至少放一件产品是通过赋初值,条件判断,状态转移三方面实现的

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    int n,m,k;
    __int64 f[11][10010];
    int num[11];
    struct brand
    {
        int b[101],c[101];
    }br[11];
    int main()
    {
        while(scanf("%d %d %d",&n,&m,&k)==3)
        {
            int a;
            memset(num,0,sizeof(num));
            for(int i=0;i<n;i++)
            {
                scanf("%d",&a);
                a;
                scanf("%d %d",&br[a].b[num[a]],&br[a].c[num[a]]);
                num[a]++;
            }
            memset(f,-1,sizeof(f));
            for(int i=0;i<=m;i++)
                f[0][i]=0;
            for(int i=1;i<=k;i++)
            {
                for(int j=0;j<num[i];j++)
                {
                    for(int l=m;l>=0;l--)
                    {
                        if(l<br[i].b[j])
                            continue;
                        if(f[i][l-br[i].b[j]]!=-1 && f[i][l]<f[i][l-br[i].b[j]]+br[i].c[j])
                            f[i][l]=f[i][l-br[i].b[j]]+br[i].c[j];
                        if(f[i-1][l-br[i].b[j]]!=-1 && f[i][l]<f[i-1][l-br[i].b[j]]+br[i].c[j])
                            f[i][l]=f[i-1][l-br[i].b[j]]+br[i].c[j];
                    }
                }
            }
            if(f[k][m]<0)puts("Impossible");
            else printf("%I64d\n",f[k][m]);
        }
        return 0;
    }
    

     hdu3535 理解了上面3033之后,这道题目其实也差不多,问题就出在赋初值的问题上了,对了每组至少选一个的情况我们已经知道了,但对于,任意选还有至多选一个的情况,初值当然是复制前一组的状态了,可是,如果不复制前一组的状态,后面的状态转移应该怎么处理,我怎么想也想不透

    #include<iostream>
    #include<algorithm>
    #define maxn 101
    #define inf 99999999
    using namespace std;
    struct object
    {
    	int c,g;
    };
    struct sett
    {
    	int k,s;
    	object w[110]; 
    }set[110];
    int T,n,m,dp[110][maxn];
    int main()
    {
    	while(scanf("%d %d",&n,&T)==2)
    	{
    		for(int i=1;i<=n;i++)
    			for(int j=0;j<=T;j++)
    				dp[i][j]=-inf;
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%d %d",&set[i].k,&set[i].s);
    			for(int j=0;j<set[i].k;j++)
    				scanf("%d %d",&set[i].w[j].c,&set[i].w[j].g);
    		}
    		for(int i=0;i<=T;i++)
    			dp[0][i]=0;
    		for(int i=1;i<=n;i++)
    		{
    			switch(set[i].s)
    			{
    			case 0:  
    				     for(int j=0;j<set[i].k;j++)	
    						 for(int t=T;t>=set[i].w[j].c;t--)
    						 { 
    			                 int v=set[i].w[j].c,cost=set[i].w[j].g;
    							 int last=dp[i-1][t-v]+cost;
    							 int cur=dp[i][t-v]+cost;
    							 dp[i][t]=max(last,max(dp[i][t],cur));
    						  }
    					 break;
    			case 1:
    				     for(int j=0;j<=T;j++)
    						 dp[i][j]=dp[i-1][j];
    				     for(int j=0;j<set[i].k;j++)
    						 for(int t=T;t>=set[i].w[j].c;t--)
    						 {
    							 int v=set[i].w[j].c,cost=set[i].w[j].g;
    							 int last=dp[i-1][t-v]+cost;
    						//	 dp[i][t]=max(dp[i][t],max(dp[i-1][t],last));
    							 dp[i][t]=max(dp[i][t],last);//要么不选,要么从上一组的状态,在当前组选一个
    						 }
    				break;
    			case 2: 
    				     for(int j=0;j<=T;j++)
    						 dp[i][j]=dp[i-1][j];
    				     for(int j=0;j<set[i].k;j++)
    						 for(int t=T;t>=set[i].w[j].c;t--)
    						 {
    							 int v=set[i].w[j].c,cost=set[i].w[j].g;
    							 int cur=dp[i][t-v]+cost;
    							 int last=dp[i-1][t-v]+cost;
    						//	 dp[i][t]=max(dp[i-1][t],max(dp[i][t],max(cur,last)));
    							 dp[i][t]=max(dp[i][t],max(last,cur));//比上一种情况多了一种选择, 就是可以从当前组继续多选择一个
    						 }
    				break;
    			}
    		}
    		if(dp[n][T]<0)
    			puts("-1");
    		else 
    		printf("%d\n",dp[n][T]);
    	}
    	return 0;
    }
    

     


     

  • 相关阅读:
    JSP第六周作业
    JSP第四次(2.0)
    JSP第四周
    软件测试课堂练习1
    5。建库,表,增删改查
    4.安卓练习
    2android九宫格
    第七周作业
    jsp第六周作业
    jsp第四周作业
  • 原文地址:https://www.cnblogs.com/nanke/p/2261695.html
Copyright © 2020-2023  润新知