Vijos P1133 装箱问题

描述

有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积 (正整数)。要求从 n 个物品中,任取若千个装入箱内,使箱子的剩余空间为最小。

格式

输入格式

第一行,一个整数,表示箱子容量;
第二行,一个整数,表示有n个物品;
接下来n行,分别表示这n个物品的各自体积。

输出格式

一个整数,表示箱子剩余空间。

分析

和之前一样,我们从决策入手,首先我们的决策和01背包一样,是当前物品是否放入,决策的策略是加入这件物品是否能让我们箱内的空间变的最小?为了更加清晰的定义出我们的策略,我们定义状态,该问题中我们的要素应该有两个,一个是序列i,还有一个是物品的体积v,从结论入手我们不难发现,我们需要定义的状态也应该是v,但是如果我们仅仅把要素v当作状态本身的话,那么我们在决策第i个物品是否放入的话,除了箱子剩下的体积已经放不下第i个物品时,其他情况只能的到“放入“这个唯一得结果,这明显是错误的,出现这样错误的原因时决策,是因为没有考虑到v这个要素(把它当做参数),综上我们的状态应该是一个把i和v当作参数,v当作本质的状态,我们定义状态f[i][c]为前i个物品在空间为c时的最大体积,这样下来我们发现其实和01背包是完全一样的问题。
//
//  main.cpp
//  装箱问题
//
//  Created by 张嘉韬 on 16/1/10.
//  Copyright © 2016年 张嘉韬. All rights reserved.
//

#include <iostream>
#include <cstdio>
using namespace std;
int f[500][200100];
int max(int a,int b)
{
    if(a>b) return a;
    else return b;
}
int main(int argc, const char * argv[]) {
    //freopen("/Users/zhangjiatao/Desktop/input.txt","r",stdin);
    int v,n,w[500];
    cin>>v>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>w[i];
    }
    for(int j=1;j<=v;j++)
    {
        if(j<w[1]) f[1][j]=0;
        else f[1][j]=w[1];
    }
    for(int i=1;i<=n;i++)
    {
        f[i][0]=0;
    }
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=v;j++)
        {
            if(w[i]<=j)
            {
                f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+w[i]);
            }
            else
            {
                f[i][j]=f[i-1][j];
            }
        }
    }
    cout<<v-f[n][v];
//    for(int i=1;i<=n;i++)
//    {
//        for(int j=1;j<=v;j++)
//        {
//            cout<<f[i][j]<<" ";
//        }
//        cout<<endl;
//    }
    return 0;
}

你可能感兴趣的:(算法,动态规划,ACM,01背包,vijos)