记忆性递归法:
此题与之前的神奇的口袋极其相似。
背包的公式推导(此题未用):
https://www.bilibili.com/video/BV1mA411n7rR?from=search&seid=15511658296152165738
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int cost[105];
int score[105];
int dp[105][1005]; //dp记忆方程
int fun(int n,int money){ //n为当前的下标,money为剩余的钱
if(dp[n][money]>0) //如果已经被递推过
return dp[n][money];
int ans;
if(n==0){ //当递归到最后的下标为0时
if(cost[n]>money) //当此时的价格大于剩余的钱返回0分
ans = 0;
else
ans = score[n]; //还有钱买最后的菜,返回最后一道菜的分
}
else if(money==0) //如果钱花完了,返回0分
ans = 0;
else if(cost[n]>money) //当前的价格大于剩余的钱,不买此菜,向前递推
ans = fun(n-1,money);
else //当前价格小于剩余的钱,可以分为买此菜和不买此菜的情况。
//买此菜时,返回值要加上当前菜的分。最后返回买与不买的最大值。
ans = max(fun(n-1,money),fun(n-1,money-cost[n])+score[n]);
dp[n][money]=ans;
return ans;
}
int main(){
int c,n;
while(scanf("%d %d",&c,&n)!=EOF){
memset(dp,0,sizeof dp);
for(int i=0;i<n;i++){
cin>>cost[i]>>score[i];
}
cout<<fun(n-1,c)<<endl;
}
return 0;
}
想当然方法【wrong】:
根据性价比排序
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef struct{
int pri,sco;
double xjb;
}cooking;
bool cmp(cooking a,cooking b){
return a.xjb>b.xjb;
}
int main(){
int c,n;
while(scanf("%d %d",&c,&n)!=EOF){
cooking a[105];
for(int i=0;i<n;i++){
cin>>a[i].pri>>a[i].sco;
a[i].xjb=1.0*a[i].sco/a[i].pri;
}
sort(a,a+n,cmp);
for(int i=0;i<n;i++){
cout<<a[i].pri<<" "<<a[i].sco<<" "<<a[i].xjb<<endl;
}
int sumf=0,ms=0;
for(int i=0;i<n;i++){
if(a[i].pri+ms<=c){
ms+=a[i].pri;
sumf+=a[i].sco;
if(ms==c)
break;
}
}
cout<<sumf<<endl;
}
return 0;
}