70分可以穷尽得出答案。该题为组合问题,可以利用回溯法穷举,但会导致运行超时
70分代码如下:
#include<iostream>
using namespace std;
#define N 35
#include<vector>
#include<climits>
int num[N];
vector<int>v;
int ans=INT_MAX;
int Bound(){
int sum=0;
for(vector<int>::iterator it=v.begin();it!=v.end();it++){
sum+=*it;
}
return sum;
}
void DFS(int n,int x,int startnum){
if(Bound()>=x){
if(Bound()<ans){
ans=Bound();
return;
}
}
if(startnum>=n){
return;
}
for(int i=startnum;i<n;i++){
if(Bound()>=x){
if(Bound()<ans){
ans=Bound();
continue;
}
}
v.push_back(num[i]);
DFS(n,x,i+1);
v.pop_back();
}
}
int main(){
int n,x;
cin>>n>>x;
for(int i=0;i<n;i++){
cin>>num[i];
}
DFS(n,x,0);
cout<<ans;
system("pause");
return 0;
}
该题可以看作是01背包问题的变形,将选最少的书达到包邮且价格最低的问题看作 选择书的价格总和尽可能达到书价格总和与包邮价格的差价(可以当作书的重量为多少价值也为多少,书的价格在不超过书价格总和与包邮价格的差价时,价值达到最大)
递推方程为:(F[i][j]指前i种商品种重量不超过j的最大价值)
F[i][j]=max(F[i-1][j],F[i-1][j-num[i]]+num[i])
满分代码如下:
#include<iostream>
#include<cmath>
using namespace std;
#define N 35
#define money 300000
int num[N];
int F[N][money];
int main(){
int n,x;
cin>>n>>x;
int s=0;
for(int i=1;i<=n;i++){
cin>>num[i];
s+=num[i];
}
int sum=s-x;
for(int i=1;i<=n;i++){
F[i][0]=0;
}
for(int i=1;i<=sum;i++){
if(num[1]<=i){
F[1][i]=num[1];
}
else{
F[1][i]=0;
}
}
int maxnum=0;
for(int i=2;i<=n;i++){
for(int j=0;j<=sum;j++){
if(num[i]<=j){
F[i][j]=max(F[i-1][j],F[i-1][j-num[i]]+num[i]);
}
else{
F[i][j]=F[i-1][j];
}
}
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=sum;j++){
// cout<<F[i][j]<<" ";
// }
// cout<<endl;
// }
cout<<s-F[n][sum]<<endl;
system("pause");
return 0;
}