描述
ctest有n个苹果,要将它放入容量为v的背包。给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值。
-
输入
- 有多组测试数据,每组测试数据第一行为2个正整数,分别代表苹果的个数n和背包的容量v,n、v同时为0时结束测试,此时不输出。接下来的n行,每行2个正整数,用空格隔开,分别代表苹果的大小c和价钱w。所有输入数字的范围大于等于0,小于等于1000。 输出
- 对每组测试数据输出一个整数,代表能放入背包的苹果的总价值。 样例输入
-
3 3 1 1 2 1 3 1 0 0
样例输出
-
2
-
-
**看完这到题,有三种思路,1,贪心,2,深搜(dfs),3,动态规划,没学动态规划的一定会优先考虑前两种方法,结果:贪心WA,深搜超时
-
1,贪心思路,按单位价值排序,然后从大到小谈,但是有有特殊情况
-
例如
-
5 5
-
1 1
-
2 2
-
3 3
-
4 4
-
5 5
-
当单位价值一样的时候,他会输出3...而这种情况下就要逼我们去遍历一遍,再做选择,当然你也可以多级排序什么的,我觉的太麻烦就跳过了,而且加了判断特殊情况后还超时了
-
下面是我的贪心代码(cin相当于scanf,cout相当与printf,>> << 表示要读入和输出的内容,其他都是c的东西)
-
#include <iostream> #include <algorithm> using namespace std; struct Node{ double c; double w; double val; }; Node apple[1010]; int compare(Node a,Node b) { return a.val > b.val; } int main() { int n,v; while(cin>>n>>v && n!=0 && v!=0) { int i,sum; for(i=0;i<n;i++) { cin>>apple[i].c>>apple[i].w; apple[i].val = apple[i].w/apple[i].c; } sort(apple,apple+n,compare); for(i=0;i<n;i++) { cout<<apple[i].c<<" "<<apple[i].w<<" "<<apple[i].val<<endl; } i = 0; sum = 0; while(v>=apple[i].c) { sum += apple[i].w; v -=apple[i].c; i++; } cout<<sum<<endl; } }
-
#include <iostream> using namespace std; int n,v; int c[1010]; int w[1010]; int themax; void dfs(int x,int t,int sum)//x表示第几个苹果,t表示当前可以装的最大体积,sum表示当前的价值 { if(x==n)//出口 return ; if(sum>themax)//更新最大值 themax = sum; dfs(x+1,t,sum);//跳过当前苹果 dfs(x+1,t-c[x],sum+w[x]);//放入当前苹果 } int main() { while(cin>>n>>v && n!=0 && v!=0) { for(int i=0;i<n;i++) { cin>>c[i]>>w[i]; themax = 0; } dfs(0,v,0); cout<<themax<<endl; } return 0; }
3.就是正解dp的方法了,
-
很多人不明白的就是
-
if(j<c[i])
dp[i+1][j] = dp[i][j];
else
dp[i+1][j] = max(dp[i][j],dp[i][j-c[i]]+w[i]);
-
这不是随随便便就写的,而是动态规划转移方程,通过推到才出来的,网上有好多讲这个的东西,多看看别人的博客,看懂为至,毕竟我菜,也说不清到不明,下面是代码
-
#include <iostream> #define max(x,y) ((x)>(y)?(x):(y)) using namespace std; int c[1010]; int w[1010]; int dp[1010][1010]; int main() { int n,v; while(cin>>n>>v && n!=0 && v!=0) { for(int i=0;i<n;i++) cin>>c[i]>>w[i]; for(int i=0;i<=n;i++) { for(int j=0;j<=v;j++) { if(j<c[i])//如果当前的放不下 dp[i+1][j] = dp[i][j];//跳过当前 else dp[i+1][j] = max(dp[i][j],dp[i][j-c[i]]+w[i]);//选择前两种方法(上一步的结果)中的较大值(放或不放) } } cout<<dp[n][v]<<endl; } return 0; }
奈何我冒泡的算法如果打动你超时的心!! -