電子科大本部食堂的飯卡有一種很詭異的設計,即在購買之前判斷余額。如果購買一個商品之前顷牌,卡上的剩余金額大于或等于5元展父,就一定可以購買成功(即使購買后卡上余額為負)返劲,否則無法購買(即使金額足夠)。所以大家都希望盡量使卡上的余額最少栖茉。
某天篮绿,食堂中有n種菜出售,每種菜可購買一次吕漂。已知每種菜的價格以及卡上的余額亲配,問最少可使卡上的余額為多少。
輸入格式:
多組數(shù)據(jù)惶凝。對于每組數(shù)據(jù):
第一行為正整數(shù)n吼虎,表示菜的數(shù)量。n<=1000苍鲜。
第二行包括n個正整數(shù)思灰,表示每種菜的價格。價格不超過50坡贺。
第三行包括一個正整數(shù)m官辈,表示卡上的余額箱舞。m<=1000。
n=0表示數(shù)據(jù)結束
輸出格式:
對于每組輸入,輸出一行,包含一個整數(shù)拳亿,表示卡上可能的最小余額晴股。
解法一:利用二進制,&運算生成子集肺魁,暴力破解
#include <iostream>
#include<math.h>
using namespace std;
const int MAX_RESULT=1001;
int main()
{
int n,result,money,temp;
while(cin>>n,n){
int price[n];
for (int i=0;i<n;i++)
{
cin>>price[i];
}
cin>>money;
result=MAX_RESULT;
for (int i=0;i<pow(2,n);i++)
{
temp=money; //temp作為臨時變量存儲錢數(shù)电湘,每一種情況都要初始化
for (int j=0;j<n;j++) //第i+1位,也就是第i個菜品
{
if((i&(1<<j))&&temp>=5)
temp-=price[j];
}
//cout<<result<<" ";
if(result>temp)
result=temp;
}
cout<<result<<endl;
}
return 0;
}
解法二:變形動態(tài)規(guī)劃
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX_LENGTH = 1005;
int price[MAX_LENGTH];
int n;
int balance;
int F[1005];
int getMaxConsumption(){
for (int i = 0; i < n-1; i++)
{
for (int V = balance; V >=price[i]; V--){
F[V] = max(F[V], F[V - price[i]] + price[i]);
}
}
return F[balance];
}
int main(){
while (cin>>n)
{
if (n == 0) break;
memset(price, 0, sizeof(int)*n);
for (int i = 0; i < n; i++)
{
scanf("%d", &price[i]);
}
scanf("%d", &balance);
if (balance < 5){ //特殊情況考慮
printf("%d\n", balance);
continue;
}
balance -= 5;
for (int i = 0; i < balance+1; i++) //范圍數(shù)組balance+1
{
F[i] = 0;
}
sort(price, price + n);
int result = getMaxConsumption();
printf("%d\n", balance-result-price[n-1]+5);//原始值盡量別改變鹅经,聲明新變量作為中間值
}
return 0;
}
注意事項
1.對子集的表示pow(2寂呛,n),用二進制來表示
2.初始化問題要注意
3.DP的變形瘾晃,一是在有個>5的限制贷痪,還有個是求最小值,最后一個是value數(shù)組和weight數(shù)組合而為一