説明
電子科技大学の食堂にあるミールカードは、購入前にバランスを判断するという非常に奇妙なデザインになっています。商品を購入する前にカードの残額が5元以上の場合は、購入に成功する必要があります(購入後にカードの残高がマイナスになった場合でも)。そうでない場合は、購入できません(金額があったとしても)。十分なものです)。したがって、誰もがカードの残高を最小限に抑えたいと考えています。
ある日、食堂ではn種類の野菜が販売されており、1品1品で購入できます。各料理の価格とカードの残高を知って、カードの最小残高をいくらにすることができるかを尋ねます。
入力
複数のデータセット。データの各グループについて:
最初の行は正の整数nで、料理の数を表します。n <= 1000。
2行目には、各料理の価格を示すn個の正の整数が含まれています。価格は50を超えません。
3行目には、カードの残高を表す正の整数mが含まれています。m <= 1000。
n = 0は、データの終わりを意味します。
出力
入力の各グループについて、出力の1行には、カードの可能な最小残高を表す整数が含まれています。
サンプル入力
1
50
5
10
1 2 3 2 1 1 2 3 2 1
50
0
サンプル出力
-45
32
アイデア:最初にすべての料理の価格を並べ替え、5元を残して最も高価なものを購入し、残りをカードm-5に入れます。状態遷移方程式:dp [j] = max(dp [j]、dp [j-price [i]] + price [i]);
#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
using namespace std;
int cmp( int a,int b )
{
return a<b;
}
int main()
{
int n,m,i,j;
while( ~scanf("%d",&n),n )
{
int dp[2016]={0},price[2016]={0};
for( i=1;i<=n;i++ )
scanf("%d",&price[i]);
sort(price+1,price+1+n,cmp);
int MAX = price[n];
scanf("%d",&m);
if( m<5 )
{
printf("%d\n",m);
continue;
}
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-MAX-dp[m]);
}
return 0;
}