第一种:
dp[j] 用前n-1个物品能否构成j元
否则,按升序排序,易证最后用5购买的菜必然是最后一个。先将背包前n-1个放入,看能放入的数据是多少,然后判断m-5后能出现哪些,利用规则替换n物品
#include<iostream> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define max(a,b) ( (a) > (b) ?(a) : (b) ) #define min(a,b) ( (a) < (b) ?(a) : (b) ) #define maxn 1100 int a[maxn]; int dp[maxn]; int main() { int n; int i,j,m; while(~scanf("%d",&n) && n) { for(i=1;i<=n;i++) scanf("%d",a+i); scanf("%d",&m); if(m<5) {printf("%d\n",m);continue;} sort(a+1,a+1+n); memset(dp,0,sizeof(dp)); dp[0]=1;int ans=0; for(i=1;i<n;i++) for(j=m+50;j>=a[i];j--) if(dp[j-a[i]]) dp[j]=1,ans=max(ans,j); if(ans+a[n]<=m) printf("%d\n",m-a[n]-ans); else { for(i=m;i>=0;i--) if(dp[i]) { if(i<=m-5) {ans=min(ans,m-i-a[n]);break;} else ans=min(ans,i); } printf("%d\n",ans); } } return 0; }
第二种:用m-5充分装菜,最后再用5装n,就可以了
dp[j] 前n-1个物品,用j元最多买多少钱的菜。
#define max(a,b) ( (a) > (b) ?(a) : (b) ) #define min(a,b) ( (a) < (b) ?(a) : (b) ) #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; int main() { int i,j,k; int t,n,m; int maxn; int dp[2014]={0},price[2014]={0}; while(scanf("%d",&n)!=EOF,n) { memset(price,0,sizeof(price)); memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) { cin>>price[i]; } cin>>m; if(m<5) { printf("%d\n",m); continue; } sort(price+1,price+n+1); maxn=price[n]; m=m-5; for(i=1;i<n;i++) { for(j=m;j>=price[i];j--) { dp[j]=max(dp[j],dp[j-price[i]]+price[i]); } } printf("%d\n",m+5-dp[m]-maxn); } return 0; } /* 1 50 5 10 1 2 3 2 1 1 2 3 2 1 50 6 10 30 45 50 25 15 111 6 10 30 45 50 25 15 4 */
原文地址:http://blog.csdn.net/gg_gogoing/article/details/40918433