洛谷每日一练5.15--P1757+P1964(分组背包)

文章目录

  • P1757
    • 题目
    • 思路
  • P1964
    • 题目
    • 思路

P1757

题目

题目描述
自 01 背包问世之后,小 A 对此深感兴趣。一天,小 A 去远游,却发现他的背包不同于 01 背包,他的物品大致可分为 k 组,每组中的物品相互冲突,现在,他想知道最大的利用价值是多少。

输入格式
两个数 m,n,表示一共有 n 件物品,总重量为 m。
接下来 n 行,每行 3 个数 a_i,b_i,c_i ,表示物品的重量,利用价值,所属组数。

输出格式
一个数,最大的利用价值。

输入输出样例
输入 #1
45 3
10 10 1
10 5 1
50 400 2

输出 #1
10
说明/提示
1≤m,n≤1000。

思路

分组背包,sum记录分组的个数,01背包模板。


#include
#include
using namespace std;
int a[1010],b[1010],c[101][20],cn[101],f[1010];
int main()
{
	int m,n,ci,sum=0;
	scanf("%d%d",&m,&n);
	for(int i=1; i<=n; i++)
	{
		scanf("%d%d%d",&a[i],&b[i],&ci);
		sum=max(sum,ci);
		cn[ci]++;
		c[ci][cn[ci]]=i;
	}
	for(int i=1; i<=sum; i++)
	{
		for(int j=m; j>=0; j--)
		{
			for(int k=1; k<=cn[i]; k++)
			{
				if(j>=a[c[i][k]])
					f[j]=max(f[j],f[j-a[c[i][k]]]+b[c[i][k]]);
			}				
		}			
	}
	printf("%d",f[m]);
	return 0; 	
}

P1964

题目

题目背景
服务器好好玩

题目描述
lcy0x1去服务器的系统商店卖东西。
一个人的背包有21格。
一开始他的背包里有m件不同的物品(不能卖)。
他要卖n种物品,每种物品有ai件,价值bi,一格可以放ci个,
名字sti(0 相同的物品可以放同一格(只要没放满)。
问他跑一次最多能卖多少钱。

输入格式
第一行m,n(0<=m<=21,0<=n<=100);
下面n行 ai,bi,ci,sti(0<=ai<=1344,0<=bi<=10000,0

输出格式
最多卖的钱s(0<=s<=1000000);

输入输出样例
输入 #1
20 3
63 1 64 yinshifen
1 10 1 men
1 1 64 yinshifen
输出 #1
64
说明/提示
多重背包
搜索0分!!!
强大的数据

思路

分组背包,用num统计不同组的个数,动态规划,状态转移方程为f[j]=max(f[j],f[j-cn]+b[i]*k)。

#include
using namespace std;
int a[1010],b[1010],c[1010],f[1010];
string name[1010];
int main()
{
	int num=1,n,m;
	scanf("%d%d",&m,&n);
	m=21-m;
	for(int i=1; i<=n; i++)
	{
		cin>>a[num]>>b[num]>>c[num]>>name[num];
		for(int j=1; j<=i-1; j++)
		{
			if(name[i]==name[j])
			{
				a[j]+=a[i];
				num--;
				break;
			}
		}
		num++;
	}
	num--;
	for(int i=1; i<=num; i++)
	{
		for(int j=m; j>=0; j--)
		{
			for(int k=0; k<=a[i]; k++)
			{
				int cn=c[i];
				while(cn)
				{
					if(cn>=k)
					{
						cn/=c[i];
						break;
					}
					cn+=c[i];
				}
				if(j-cn<0) 
					break;
				f[j]=max(f[j],f[j-cn]+b[i]*k);
			}
		}
	}
	printf("%d",f[m]);
	return 0;
}

你可能感兴趣的:(每日打卡)