装载问题 贪心转化为01背包问题DP解决(自己编了一道题)

刚刚上完算法课,讲了装载问题,挺有用的,感觉比赛里可能会出现类似的,我去各大oj搜了一下,没有现成的题目,于是自己编了一道题。这是我模仿编的题,基本上就是模板题,没挖坑,自己也没有准确的测试数据,自己试了几个例子反正是没啥问题,不知道自己代码对不对,欢迎大家来批评指正。


Loading problem

Time Limit: 1 Seconds       Memory Limit: 65536 KB

There are two trucks loading goods.The maximum carrying capacity of the two vehicles are c1 and c2.Here are n goods with the weight v1、v2、v3……Now,we are to calculate whether all goods can be loaded into the trucks in one time.

Input

There are multiple test cases. The first line of input is an integer T  indicating the number of test cases.

For each test case,there are two lines followed.

The first line of each test case contains 3 positive integers n, c1and c2(0<n<=1000;   0<c1,c2<=1000) ,

The second line contains n positive integers Separated by a space,

Output

For each test case If all goods can be loaded, output "YES". Otherwise, output "NO".

Sample Input

5

4 100 200

100 100 80 20

2 20 30

15 31

1 300 800

900

8 200 160

10 20 30 40 50 60 70 80

8 200 160

10 23 33 43 50 56 66 79

Sample Output

YES

NO

NO

YES

NO




解题思路:首先是一种贪心的思想,先把一个车子尽可能的装满,留的空隙越少越好,如果不能装的再多了,那么剩下的都装到另一个车子里,如果第二个车子能装下就装,装不下就返回“NO”。在装第一个车子的时候,用到了01背包的动态规划问题,因为时间复杂度是n*c,所以,我们从c1和c2里挑个比较小的c来算,省时间。算出了第一个车子装下的最大值后,后面用总量作差跟第二个车子比较一下就行了。

个人感想:我编的这个题是个模板题,其实比赛里可能会有三辆车。。。那就两次动态规划就好,但是第一次动态规划的时候要把自己用了哪些背包记录一下,然后删去,再进行第二次。


#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int INF=0x7fffffff;
const int MAX_N=1009;

int T,c1,c2,n;
int A[MAX_N];
int dp[MAX_N][MAX_N];

int main(){
    cin>>T;
    while(T--){
        int sum=0;
        memset(dp,-1,sizeof(dp));
        scanf("%d%d%d",&n,&c1,&c2);
        if(c1>c2)swap(c1,c2);
        for(int i=0;i<n;i++){
            scanf("%d",&A[i]);
            sum+=A[i];
        }

        for(int i=0;i<=c1;i++){
            dp[n][i]=0;
        }

        for(int i=n-1;i>=0;i--){
            for(int j=0;j<=c1;j++){
                if(A[i]>j){
                    dp[i][j]=dp[i+1][j];
                }
                else{
                    dp[i][j]=max(dp[i+1][j],dp[i+1][j-A[i]]+A[i]);
                }
            }
        }

        if(sum-dp[0][c1]<=c2)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值