给定n个物品的重量和两艘载重量分别为c1和c2的船,问能否用这两艘船装下所有的物品。
输入包含多组测试数据,每组测试数据由若干行数据组成。
第一行为三个整数,n c1 c2,(1 <= n <= 100),(1<=c1,c2<=5000)。
接下去n行,每行一个整数,代表每个物品的重量(重量大小不大于100)。
对于每组测试数据,若只使用这两艘船可以装下所有的物品,输出YES。
否则输出NO。
3 5 8 6 3 3 3 5 8 5 3 4
NO YES
这道题是典型的背包问题,我们可以把问题转为:
在一条船上尽可能多的放置货物,然后看剩下的货物另外一条船能否装下。
dp[j]表示容量为j的船只 所能装的最多的货物量,每次考虑一个货物,更新dp[j]
for(int j = smallBoat; j>=boatw[i]; j--){ dp[j] = std::max(dp[j],boatw[i]+dp[j-boatw[i]]);
注意更新dp[j]一定是从高到低更新。原因可参考题目1209:最小邮票数
类似的题目有
我们仿照题目1420:Jobdu MM分水果 用另外一种方式实现求船的最大载重。
也就是 在给定船只大小smallboat,和货物重量的情况下,哪些实际装载量可以实现。
booldp[j] 为真表示可以实现j个装载量,更新过程如下
for(int j = smallBoat; j>=boatw[i]; j--){ booldp[j] = booldp[j] || booldp[j-boatw[i]]; }需要注意的是 booldp[0] 一定要设置为true,因为在船上一个货物都不放,就是0,booldp[0]=true.
算法的时间复杂度与smallboat有关,所以如果两只船只重量相差很大的话,对小船求最大载重可以减少程序时间。
普通背包问题
题目1364:v字仇杀队
题目1462:两船载物问题
题目1455:珍惜现在,感恩生活
题目1209:最小邮票数
题目1420:Jobdu MM分水果
项目安排类题目
题目1499:项目安排
题目1463:招聘会
题目1434:今年暑假不AC
资源无限求最大值的题目。
题目1494:Dota
源程序
//============================================================================ // Name : judo1462.cpp // Author : wdy // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ //similar to 1420 #include <iostream> #include <stdio.h> #include <cstring> using namespace std; //::vector<int> wts; int boatw[101]={0}; int dp[5001]={0}; int sumw = 0; void init(int n){ sumw = 0; for(int i = 1;i<n+1;i++){ scanf("%d",boatw+i); sumw+=boatw[i]; } } void judge(int n,int smallBoat,int bigBoat){ if(sumw > smallBoat+bigBoat){ printf("NO\n"); return; } // *dp = new int[boat1 + 1]; memset(dp,0,(smallBoat+1)*sizeof(int)); for(int i = 1;i<n+1;i++){ for(int j = smallBoat; j>=boatw[i]; j--){ dp[j] = std::max(dp[j],boatw[i]+dp[j-boatw[i]]); } } if(sumw - dp[smallBoat] <=bigBoat ){ printf("YES\n"); }else printf("NO\n"); } void judgenew(int n,int smallBoat,int bigBoat){//using bool if(sumw > smallBoat+bigBoat){ printf("NO\n"); return; } bool *booldp = new bool[smallBoat + 1]; memset(booldp,0,(smallBoat+1)*sizeof(bool)); booldp[0] = true;//Attention must be true for(int i = 1;i<n+1;i++){ for(int j = smallBoat; j>=boatw[i]; j--){ booldp[j] = booldp[j] || booldp[j-boatw[i]]; } } for(int i = smallBoat;i>=0;i--){ if(booldp[i]){ if(sumw - i<=bigBoat) printf("YES\n"); else printf("NO\n"); return; } } } void judo(){ int n; int boat1; int boat2; while(scanf("%d %d %d",&n,&boat1,&boat2)!=EOF){ init(n); if(boat1<boat2) judgenew(n,boat1,boat2); else judgenew(n,boat2,boat1); } } int main() { judo(); return 0; } /************************************************************** Problem: 1462 User: KES Language: C++ Result: Accepted Time:10 ms Memory:1540 kb ****************************************************************/