点击打开链接
题意:
给你n件物品,m元钱,以及n件物品的价格,求最多物品数的方案数;
刚开始,yf说可以先排序贪心求出最多的件数,然后按照完全背包的思路求解,
#include"stdio.h" #include"string.h" #include"algorithm" using namespace std; #define N 505 int main() { int T; int n,m,t; int i,j,k; int A[33]; int dp[N][33]; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&A[i]); sort(A+1,A+n+1); int ans; ans=0;t=0; for(i=1;i<=n;i++) { if(ans+A[i]<=m) ans+=A[i],t=i; else break; } if(t==n) { printf("You have 1 selection(s) to buy with %d kind(s) of souvenirs.\n",n); continue; } if(t==0) { printf("Sorry, you can't buy anything.\n"); continue; } memset(dp,0,sizeof(dp)); for(i=0;i<=m;i++)dp[i][0]=1; for(i=1;i<=n;i++) { for(j=m;j>=A[i];j--) { for(k=t;k>=1;k--) dp[j][k]+=dp[j-A[i]][k-1]; } } if(dp[m][t]==0) printf("Sorry, you can't buy anything.\n"); else printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.\n",dp[m][t],t); } return 0; }
其实 按照直接dp的话也是可以,定义一个dp[505][2],dp[i][0]表示花j元买的最多的物品数,dp[i][1]表示花j元买最多物品的方案数
dp[i][0]=max(dp[i-a][0]+1,dp[i][0])
如果取前者,说明最大件数增加了,则dp[i][1]=dp[i-a][1]
如果取后者,说明最大件数不变,dp[i][1]+=dp[i-a][1];
#include"stdio.h" #include"string.h" #define N 505 int main() { int T; int n,m; int i,j; int A[33]; int dp[N][2]; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&A[i]); memset(dp,0,sizeof(dp)); for(i=0;i<=m;i++)dp[i][1]=1; for(i=1;i<=n;i++) { for(j=m;j>=A[i];j--) { if(dp[j-A[i]][0]+1>dp[j][0]) { dp[j][0]=dp[j-A[i]][0]+1; dp[j][1]=dp[j-A[i]][1]; } else if(dp[j-A[i]][0]+1==dp[j][0]) { dp[j][1]+=dp[j-A[i]][1]; } } } if(dp[m][0]==0) printf("Sorry, you can't buy anything.\n"); else printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.\n",dp[m][1],dp[m][0]); } return 0; }