網上分析:ios
設餘額爲m,令s=m-5,那麼咱們就要找使得容量爲s的揹包最後剩的空間最小的方法,找到以後再用這個剩餘容量+5-最大的那個沒有被選的商品價值就是最小余額.spa
可是如今咱們不知道最後須要減的那個物品應該是哪一個,能夠證實最後須要減的那個物品必定是價值最大的那個.證實:設計
假設價值最大的爲max,且咱們假設存在最優的狀況(使餘額最小)下max物品不是最後一個被減的,最後一個被減的商品價值爲mid,假設此時的餘額爲x.那麼仔細想一想若是咱們把max和mid的位置互換,依然能夠獲得餘額爲x.(仔細想一想是否是)code
我的心得:這麼經典簡單的揹包問題都懵逼了,真的是沒誰了。不過確實腦瓜子不夠機靈,你想呀,直接DP的花邊界難肯定還有負數,這樣把5單獨拿出來,blog
就能夠徹底轉化爲揹包問題了,其實一開始拿出來後我仍是很懵逼的,後面轉念一想,拿出來後裝最大值而後相減不就剩下的最小余額了嗎,真的是一道好題。ip
真的是水得不行。ci
Input多組數據。對於每組數據:
第一行爲正整數n,表示菜的數量。n<=1000。
第二行包括n個正整數,表示每種菜的價格。價格不超過50。
第三行包括一個正整數m,表示卡上的餘額。m<=1000。
n=0表示數據結束。
Output對於每組輸入,輸出一行,包含一個整數,表示卡上可能的最小余額。Sample Inputstring
1 50 5 10 1 2 3 2 1 1 2 3 2 1 50 0
Sample Outputit
-45 32
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iomanip> 6 #include<algorithm> 7 using namespace std; 8 const int maxn=1005; 9 int n,sum; 10 int cai[1005]; 11 bool cmp(int a,int b) 12 { 13 return a>b; 14 } 15 int ways[1005]; 16 int main() 17 { 18 while(cin>>n&&n!=0){ 19 for(int i=1;i<=n;i++) 20 cin>>cai[i]; 21 cin>>sum; 22 sort(cai+1,cai+n+1); 23 if(sum<5) 24 cout<<sum<<endl; 25 else { 26 int ends=5-cai[n]; 27 sum=sum-5; 28 memset(ways,0,sizeof(ways)); 29 for(int i=1;i<=n-1;i++) 30 for(int j=sum;j>=cai[i];j--) 31 ways[j]=max(ways[j],ways[j-cai[i]]+cai[i]); 32 cout<<sum-ways[sum]+ends<<endl; 33 } 34 35 } 36 return 0; 37 }