Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 19878 Accepted Submission(s): 6916
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。
n=0表示数据结束。
1.如果m<5 ,那么什么都买不了,输出 m
2.如果m>5,(1)如果所有物品之和都小于m,那么直接输出m-物品之和(全都买了)
(2)如果m不够,那么背包容量为m-5,那么求解出dp[m-5](dp[i]表示剩余容量为i的背
包能够获取的最大价值),剩下5元去买最大价值的东西
输出 m - max_value - dp[m-5]
状态转移方程 dp[i] = max(dp[i],dp[i-V[i]]+W[i](此题背包消耗的容量和获取的价值相等)
///分析:看题意就知道是01背包问题 ///1.如果m<5 ,那么什么都买不了,输出 m ///2.如果m>5,(1)如果所有物品之和都小于m,那么直接输出m-物品之和(全都买了) /// (2)如果m不够,那么背包容量为m-5,那么求解出dp[m-5](dp[i]表示容量为i的背 /// 包能够获取的最大价值),剩下5元去买最大价值的东西 /// 输出 m - max_value - dp[m-5] ///状态转移方程 dp[i] = max(dp[i],dp[i-V[i]]+W[i](此题背包消耗的容量和获取的价值相等) #include<stdio.h> #include<algorithm> #include<string.h> #include<iostream> #define N 1005 using namespace std; int W[N]; int dp[N]; int main() { int n,m; while(scanf("%d",&n)!=EOF,n){ int sum = 0; for(int i=1;i<=n;i++){ int t; scanf("%d",&t); W[i]=t; sum+=W[i]; } sort(W+1,W+n+1); scanf("%d",&m); if(m<5){ printf("%d\n",m); continue; } if(sum<=m){ printf("%d\n",m-sum);continue; } memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ for(int v = m-5;v>=W[i];v--) {///容量为v的背包最多能放多少价值的东西 dp[v] = max(dp[v],dp[v-W[i]]+W[i]); } } //printf("%d %d %d\n",m,dp[m-5],W[n]); int v = m-dp[m-5]-W[n]; printf("%d\n",v); } return 0; }