poj1276



#include<iostream>
using namespace std;

int main(int i,int j)
{
	int N;   //物品种数(面额种数)	
	int cash;  //背包容量(最大可取金额)
	while(cin>>cash>>N)
	{
		/*Input*/

		int* n=new int[N+1];  //n[i]第i种物品的个数(第i种面额的数量)
		int* w=new int[N+1];  //w[i]第i种物品的价值(第i种面额的价值)
		int* c=new int[N+1];  //c[i]第i种物品的体积(第i种面额消耗的价值)
		int* dp=new int[cash+1];  //dp[j]记录的是 当前最接近状态j且<=j的值,dp值会累积
		int* count=new int[cash+1];//计数器,限制某种物品(面额)的选取个数

		for(i=1;i<=N;i++)
		{
			cin>>n[i]>>w[i];
			c[i]=w[i];    //本题的单个物品的“体积”等于其“价值”
		}
		
		/*Initial*/

		memset(dp,0,4*(cash+1));  //由于dp申请的是动态内存,用sizeof计算长度会出错
		                          //这里要用 类型大小*个数,这里为 int*(cash+1) , int大小为4

		/*DP*/
		
		for(i=1;i<=N;i++)
		{
			memset(count,0,4*(cash+1));  //每更换一次面额,计数器清零
			for(j=w[i];j<=cash;j++)      //对于第i种货币,其面额d[i]~cash间任一个状态都可能发生
				if(dp[j]<dp[j-c[i]]+w[i] && count[j-c[i]]<n[i]) //count[j-c[i]]<n[i]
				{                                               //取某种面额前,必须保证这次操作之前所取该种面额的次数小于n[i]
					dp[j] = dp[j-c[i]]+w[i];    //选取第i个物品后,背包容量(允许取的最大金额)减少c[i]
					count[j]=count[j-c[i]]+1;   //对于当前状态j,第i种面额被抽了count[j]次
				}
		}

		/*Output*/
		
		cout<<dp[cash]<<endl;


		delete n;
		delete w;
		delete c;
		delete dp;
		delete count;
	}
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值