1. 程式人生 > >nssl1231-Gift【01揹包,dp】

nssl1231-Gift【01揹包,dp】

正題

題目大意

n個物品,每個物品有cic_i元,求有多少種方案數使得無法再買另外任何的東西。

解題思路

我們發現其實對於每種方案判斷只需要考慮剩下的最小的哪一個,所以我們可以將cc從小到大排序。然後用fi,jf_{i,j}表示選擇了1i11\sim i-1還沒有選擇時,耗費了j元的方案數。 動態轉移: fi,j=fi+1,j+ci+fi+1,jf_{i,j}=f_{i+1,j+c_i}+f_{i+1,j} 最後我們列舉最小沒有選擇的是xx,還剩餘resresr=0cx1fn,mr\sum_{r=0}^{c_x-1}f_{n,m-r}

code

#include<cstdio>
#include<algorithm>
#define N 2010
#define XJQ int(1e7+7)
using namespace std;
int n,m,c[N],f[N][N],ans,t;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	  scanf("%d",&c[i]),ans+=c[i];
	if(ans<=m)
	{
		printf("1");
		return
0; } ans=0; sort(c+1,c+1+n);//排序 f[n+1][0]=1;//初始化 for(int i=n;i>=1;i--) for(int j=0;j<=m;j++) f[i][j]=(f[i+1][j]+(j>=c[i]?f[i+1][j-c[i]]:0))%XJQ; //動態轉移 for(int i=1;i<=n;i++) { for(int j=0;j<c[i];j++) if(m-t-j>=0) (ans+=f[i+1][m-t-j])%=XJQ;//計算答案 t+=c[i];//減少剩餘
} printf("%d",ans); }