• 【6666】分组背包


    【问题描述】
    一个旅行者有一个最多能装V公斤的背包,现在有n件物品,它们的重量分别是W1,W2,···,Wn,它们的价值分别是C1,C2,···,Cn。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
    【输入格式】
    第1行:三个整数,V(背包容量,V<=200),n(物品数量,N<=30)和T(最大组号,T <= 10);
    第2至N+1行:每行三个整数Wi,Ci,P,表示每个物品的重量、价值、所属组号。
    【输出格式】
    仅一行,一个数,表示最大总价值。
    【输入样例】
    10 6 3
    2 1 1
    3 3 1
    4 8 2
    6 9 2
    2 8 3


    3 9 3
    【输出样例】

    20


    【题解】

    对于每一个组而言,只有选其中一个或者全不选。

    枚举每一组,然后枚举容量,最后枚举该组中的所有物品。这样可以做到每组中的物品只会被选一次。

    这里和0/1背包的差别就是,0/1背包是枚举单个物品,对单个物品都进行考虑是否要拿。而分组背包,则是在组的前提下,对每个组内的物品进行决策,就是说把每个物品都放一下看看在j容量时,哪一个更优。

    f[j]表示容积不超过j时,物品所能获得的最大收益。

    【代码】

    #include <cstdio>
    #include <cstring>
    
    int v,n,t,w[50],c[50],a[15][50],f[250];
    
    void input_data()
    {
    	scanf("%d%d%d",&v,&n,&t);
    	for (int i = 1;i <= n;i++)
    		{
    			int p;
    			scanf("%d%d%d",&w[i],&c[i],&p);
    			a[p][++a[p][0]] = i; //把这个物品存在p组的a[p][0]位置.a[p][0]用于存储物品p组物品个数. 
    		}
    }
    
    void get_ans()
    {
    	memset(f,0,sizeof(f));
    	for (int i = 1;i <= t;i++) //枚举组 
    		for (int j = v;j >=0;j--) //枚举背包的容量 
    			for (int k = 1;k <= a[i][0];k++) //枚举该组内的所有物品 
    				if (j-w[a[i][k]] >=0) //如果能够装的下 
    					{
    						if (f[j] < f[j-w[a[i][k]]]+c[a[i][k]]) //尝试用该物品更新该容积下的最优值 
    							f[j] = f[j-w[a[i][k]]] + c[a[i][k]];
    					}	
    }
    
    void output_ans()
    {
    	printf("%d",f[v]);	
    }
    
    int main()
    {
    	//freopen("F:\rush.txt","r",stdin);
    	input_data();
    	get_ans();
    	output_ans();
    	return 0;
    }	


  • 相关阅读:
    fatal error C1902: 程序数据库管理器不匹配;请检查安装 (zz)
    c++ std string reserve 测试
    2018年长沙理工大学第十三届程序设计竞赛
    2018年东北农业大学春季校赛
    从本质看海明码——海明码的由来
    CodeForces475
    一维背包问题
    2018年长沙理工大学第十三届程序设计竞赛 箱庭的股市
    高精度加法模板
    for,while,do while
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632390.html
Copyright © 2020-2023  润新知