https://www.luogu.org/problemnew/show/P1616

完全背包,可以用一个常数优化,对于同一个价值的量,仅保存花费最小的那个就行了,因为每种都有无限多个。

#include<bits/stdc++.h>
using namespace std;

int n,V;
int c[10005],w[10005];
int d[100005];

int MinCost[10005],pos;

void CompletePack()
{
	for(int i=1;i<=n;i++)
	  for(int j=c[i];j<=V;j++)d[j]=max(d[j],d[j-c[i]]+w[i]); 	     
}

void init()
{
	cin>>V>>n;
	int pertime,value;
	for(int i=1;i<=n;i++)
	{
		cin>>pertime>>value;
		if(0==MinCost[value])
		{
			MinCost[value]=++pos;
			c[pos]=pertime;
			w[pos]=value;
		}
		else if(pertime<c[MinCost[value]])
		{
			c[MinCost[value]]=pertime;
			w[MinCost[value]]=value;
		}
	}
	n=pos;
}

int main()
{
	freopen("input.in","r",stdin);
	init();
	CompletePack();
	cout<<d[V]<<endl;
	
	return 0;
} 

后来想快些,看错题本来是每个草药价值小于10000,结果看成草药总价值小于10000,于是想,用p(i,j)表示前i个物品价值为j用的最小花费。

初始化p(0,0)=0,p(0,j)=INF.             状态转移方程p(i,j)=min{p(i-1,j),p(i-1,j-w(i))+c(i)}

最后找最大的时间小于要求的价值就ok了,然后wa了,一组没过,才发现看错了题。