• 【9926】完全背包


    Time Limit: 1 second
    Memory Limit: 128 MB

    【问题描述】

    设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中
    选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。

    【输入格式】

    第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30);
    第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。

    【输出格式】

    仅一行,一个数,表示最大总价值。

    Sample Input

    10 4
    2  1
    3  3
    4  5
    7  9
    
    【题解】
    【法一】
    设f[i][j]表示前i个物品,所用的容量不超过j所能获得的最大价值。
    f[i][j] = max{f[i-1][j],f[i-1][j-k*w[i]] + k*c[i]}; (k*w[i] <=j)
    对于第i个物品,可以选择不拿(f[i-1][j]),也可以任意选择k个。
    这种二维的存储方式比较容易理解。
    #include <cstdio>
    #include <cstring>
    
    int m,n,f[31][250],w[50],c[50];
    
    void input_data()
    {
    	scanf("%d%d",&m,&n);
    	for (int i = 1;i <= n;i++) //êäèë¸÷¸öÎïÆ·μÄDÅÏ¢ 
    		scanf("%d%d",&w[i],&c[i]);
    }	
    
    void get_ans()
    {
    	memset(f,0,sizeof(f));			 
    	for (int i = 1;i <= n;i++)
    		for (int j = m;j >= 0;j--)
    			{
    				f[i][j] = f[i-1][j];
    				int k = 1;
    				while (k*w[i] <= j)
    					{
    						if (f[i][j] < f[i-1][j-k*w[i]] + k*c[i])
    							f[i][j] = f[i-1][j-k*w[i]] + k*c[i];
    						k++;
    					}
    			}
    }
    
    void output_ans()
    {
    	printf("max=%d",f[n][m]);	
    }
    
    int main()
    {
    	//freopen("F:\rush.txt","r",stdin);
    	input_data();
    	get_ans();
    	output_ans();
    	return 0;	
    }
    【法二】
    设f[j]表示容量不超过j的背包所能装得的最大价值。
    f[j] = max{f[j],f[j-w[i]] + c[i]};
    这次j层循环要正向进行。
    假设一个物品的重量为1.
    你更新完f[5],又可以更新f[6],f[7]...这样就达到了每个物品可以多次拿的效果。
    #include <cstdio>
    #include <cstring>
    
    int m,n,f[250],w[50],c[50];
    
    void input_data()
    {
    	scanf("%d%d",&m,&n);
    	for (int i = 1;i <= n;i++) 
    		scanf("%d%d",&w[i],&c[i]);
    }	
    
    void get_ans()
    {
    	memset(f,0,sizeof(f));			 
    	for (int i = 1;i <= n;i++)
    		for (int j = w[i];j <= m;j++) //一定要正向循环。 
    			if (f[j-w[i]] + c[i] > f[j]) //这里就省掉了一层k循环。 
    				f[j] = f[j-w[i]] + c[i];
    }
    
    void output_ans()
    {
    	printf("max=%d",f[m]);	
    }
    
    int main()
    {
    	//freopen("F:\rush.txt","r",stdin);
    	input_data();
    	get_ans();
    	output_ans();
    	return 0;	
    }




  • 相关阅读:
    下四国的排长和下四国的小兵 (转载)
    RSS Bandit 不能显示中文界面的解决方法
    Google桌面搜索(GDS)插件的开发工具
    编写VxWorks的Hello World程序
    Visual Studio 2005 Express October 2004 CTP完整版本的下载
    压缩.NET可执行文件的工具
    支持x64的开发工具
    Visual Studio.NET 2002的Service Pack 1发布了
    Windows 嵌入式开发的一些Blog
    利用BITSADMIN获得下载地址
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632395.html
Copyright © 2020-2023  润新知