飯卡(01揹包問題)

網上分析:ios

       設餘額爲m,令s=m-5,那麼咱們就要找使得容量爲s的揹包最後剩的空間最小的方法,找到以後再用這個剩餘容量+5-最大的那個沒有被選的商品價值就是最小余額.spa

可是如今咱們不知道最後須要減的那個物品應該是哪一個,能夠證實最後須要減的那個物品必定是價值最大的那個.證實:設計

假設價值最大的爲max,且咱們假設存在最優的狀況(使餘額最小)下max物品不是最後一個被減的,最後一個被減的商品價值爲mid,假設此時的餘額爲x.那麼仔細想一想若是咱們把max和mid的位置互換,依然能夠獲得餘額爲x.(仔細想一想是否是)code

 

我的心得:這麼經典簡單的揹包問題都懵逼了,真的是沒誰了。不過確實腦瓜子不夠機靈,你想呀,直接DP的花邊界難肯定還有負數,這樣把5單獨拿出來,blog

就能夠徹底轉化爲揹包問題了,其實一開始拿出來後我仍是很懵逼的,後面轉念一想,拿出來後裝最大值而後相減不就剩下的最小余額了嗎,真的是一道好題。ip

真的是水得不行。ci

電子科大本部食堂的飯卡有一種很詭異的設計,即在購買以前判斷餘額。若是購買一個商品以前,卡上的剩餘金額大於或等於5元,就必定能夠購買成功(即便購買後卡上餘額爲負),不然沒法購買(即便金額足夠)。因此你們都但願儘可能使卡上的餘額最少。 
某天,食堂中有n種菜出售,每種菜可購買一次。已知每種菜的價格以及卡上的餘額,問最少可以使卡上的餘額爲多少。 

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 }
相關文章
相關標籤/搜索