Bone Collector HDU - 2602(0/1背包)

本文深入探讨了背包问题的经典案例,包括骨收集者问题和留学申请概率计算。通过详细解析两种问题的算法实现,揭示了0/1背包问题的解决策略,如动态规划的应用,以及如何在资源有限的情况下最大化目标函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave … 
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ? 

 

Input

The first line contain a integer T , the number of cases. 
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.

Output

One integer per line representing the maximum of the total value (this number will be less than 2 31).

Sample Input

1
5 10
1 2 3 4 5
5 4 3 2 1

Sample Output

14

思路:本题只需要填表,找到背包可能得到的最大价值,v[i][j]表示前i个物品放入剩余空间为j的背包中,能得到的最大价值,如果剩余空间不够装第i个物品,即volume[i]>j,第i件物品就不能被放入,此时v[i][j]=v[i-1][j],即把前i个物品放入剩余空间为j的背包的得到的价值等于把前i-1个物品放入剩余空间为j的背包得到的价值;如果剩余空间够装第i个物品,则v[i][j]=v[i-1][j-volume[i]]+value[i],即把前i个物品放入剩余空间为j的背包的价值等于把前i-1个物品放入剩余空间为j-volume[i](原来空间是j,但放入物品i后,就只剩下j-volume[i]的空间给前i-1件物品放了)的背包中得到的价值再加上第i件物品本身的价值。本题填表用的是二维空间。

如果要压缩成一维空间,代码如下:

for(int i=1; i<=n; i++)//这里不需要用到i-1所以i从1开始
    for(int j=c; j>=volume[i]; j--)
    //逆序遍历,并且只遍历到当前volume[i],
    //保证都是可以放下的(j>=volume[i]),那么没被遍历到的v[j]都是放不下的,
    //值没有被替换和覆盖,所以是上一状态的值,也就是放入前i-1件物品时,v[j]的值。
    {
         v[j]=max(v[j],v[j-volume[i]]+value[i]);
    }
#include <iostream>
#include <algorithm>
#define MAXN 1005
#define MAXV 1005
using namespace std;
int v[MAXN][MAXV];
int value[MAXN];
int volume[MAXN];
void FillTable(int n,int c)//n是个数,c是总容量
{
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=c;j++)//从0开始意味增量0也可以计算
        {
            if(volume[i]>j)//装不下
            {
                v[i][j]=v[i-1][j];//v[i-1]的状态要存在,所以i从1开始
            }
            else
            {
                v[i][j]=max(v[i-1][j],v[i-1][j-volume[i]]+value[i]);//后面的价值不一定比前面的大,要做比较
            }
        }
    }
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(v,0,sizeof(v));
        memset(value,0,sizeof(value));
        memset(volume,0,sizeof(volume));
        int n,c;
        cin>>n>>c;//n个数,c总容量
        for(int i=1;i<=n;i++)
        {
            cin>>value[i];//输入价值
        }
        for(int i=1;i<=n;i++)
        {
            cin>>volume[i];//输入体积
        }
        FillTable(n,c);
        cout<<v[n][c]<<endl;
    }
    return 0;
}

变形

I NEED A OFFER! HDU - 1203

Speakless很早就想出国,现在他已经考完了所有需要的考试,准备了所有要准备的材料,于是,便需要去申请学校了。要申请国外的任何大学,你都要交纳一定的申请费用,这可是很惊人的。Speakless没有多少钱,总共只攒了n万美元。他将在m个学校中选择若干的(当然要在他的经济承受范围内)。每个学校都有不同的申请费用a(万美元),并且Speakless估计了他得到这个学校offer的可能性b。不同学校之间是否得到offer不会互相影响。“I NEED A OFFER”,他大叫一声。帮帮这个可怜的人吧,帮助他计算一下,他可以收到至少一份offer的最大概率。(如果Speakless选择了多个学校,得到任意一个学校的offer都可以)。 

Input

输入有若干组数据,每组数据的第一行有两个正整数n,m(0<=n<=10000,0<=m<=10000) 
后面的m行,每行都有两个数据ai(整型),bi(实型)分别表示第i个学校的申请费用和可能拿到offer的概率。 
输入的最后有两个0。 

Output

每组数据都对应一个输出,表示Speakless可能得到至少一份offer的最大概率。用百分数表示,精确到小数点后一位。 

Sample Input

10 3
4 0.1
4 0.2
5 0.3
0 0

Sample Output

44.0%


        
  

Hint

You should use printf("%%") to print a '%'.

思路:

属于0/1背包问题,题目要求的是至少得到一份offer的最大概率,可以转化为求一份offer都得不到的最小概率。p(得不到某份offer)=1-p(得到某份offer)。dp[j]表示用剩下j万元申请i个学校的offer不成功的概率,当cost[i]>j,说明剩下j万元申请不到第i个学校的offer,dp[0~j]保留上一次循环的结果,dp[j~i]更新为dp[j]和dp[j-cost[i]]*(1.0-chance[i])中的较小值。

#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int cost[10005];
double chance[10005];
double dp[10005];
int main()
{
    int n,m;
    while(cin>>n>>m&&n+m)//m学校n钱
    {
        for(int i=0;i<=n;i++)
        {
            dp[i]=1.0;
        }
        for(int i=1; i<=m; i++)
        {
            cin>>cost[i]>>chance[i];
        }
        for(int i=1; i<=m; i++)
            for(int j=n; j>=cost[i]; j--)
            {
                dp[j]=min(dp[j],dp[j-cost[i]]*(1.0-chance[i]));
            }
        printf("%.1f%%\n",(1.0-dp[n])*100);
    }
    return 0;
}

 

帮我在每行代码后用中文注释出意思与作用,不要改变代码 结构,#pragma once //============================================================================== // WARNING!! This file is overwritten by the Block Styler while generating // the automation code. Any modifications to this file will be lost after // generating the code again. // // Filename: D:\FXM\Documents\nx_customized\23-RuledFaces\RuledFaces.hpp // // This file was generated by the NX Block Styler // Created by: fxm2hh // Version: NX 2212 // Date: 07-17-2025 (Format: mm-dd-yyyy) // Time: 14:33 // //============================================================================== #ifndef RuledFaces_H_INCLUDED #define RuledFaces_H_INCLUDED //------------------------------------------------------------------------------ //These includes are needed for the following template code //------------------------------------------------------------------------------ #include <uf_defs.h> #include <uf_ui_types.h> // Internal Includes #include <NXOpen/ListingWindow.hxx> #include <NXOpen/Session.hxx> #include <NXOpen/UI.hxx> #include <NXOpen/NXMessageBox.hxx> #include <NXOpen/Callback.hxx> #include <NXOpen/NXException.hxx> #include <NXOpen/BlockStyler_UIBlock.hxx> #include <NXOpen/BlockStyler_BlockDialog.hxx> #include <NXOpen/BlockStyler_PropertyList.hxx> #include <NXOpen/BlockStyler_Group.hxx> #include <NXOpen/BlockStyler_ObjectColorPicker.hxx> #include <NXOpen/BlockStyler_BodyCollector.hxx> #include <NXOpen/BlockStyler_Separator.hxx> #include <NXOpen/BlockStyler_FaceCollector.hxx> #include <iostream> #include <unordered_map> #include <unordered_set> #include "NXOpen_ALL.h" #include "uf_all.h" //------------------------------------------------------------------------------ //Bit Option for Property: EntityType //------------------------------------------------------------------------------ #define EntityType_AllowBodies (1 << 6); //------------------------------------------------------------------------------ //Bit Option for Property: BodyRules //------------------------------------------------------------------------------ #define BodyRules_SingleBody (1 << 0); #define BodyRules_FeatureBodies (1 << 1); #define BodyRules_BodiesinGroup (1 << 2); //------------------------------------------------------------------------------ //Bit Option for Property: EntityType //------------------------------------------------------------------------------ #define EntityType_AllowFaces (1 << 4); #define EntityType_AllowDatums (1 << 5); //------------------------------------------------------------------------------ //Bit Option for Property: FaceRules //------------------------------------------------------------------------------ #define FaceRules_SingleFace (1 << 0); #define FaceRules_RegionFaces (1 << 1); #define FaceRules_TangentFaces (1 << 2); #define FaceRules_TangentRegionFaces (1 << 3); #define FaceRules_BodyFaces (1 << 4); #define FaceRules_FeatureFaces (1 << 5); #define FaceRules_AdjacentFaces (1 << 6); #define FaceRules_ConnectedBlendFaces (1 << 7); #define FaceRules_AllBlendFaces (1 << 8); #define FaceRules_RibFaces (1 << 9); #define FaceRules_SlotFaces (1 <<10); #define FaceRules_BossandPocketFaces (1 <<11); #define FaceRules_MergedRibFaces (1 <<12); #define FaceRules_RegionBoundaryFaces (1 <<13); #define FaceRules_FaceandAdjacentFaces (1 <<14); #define FaceRules_HoleFaces (1 <<15); //------------------------------------------------------------------------------ // Namespaces needed for following template //------------------------------------------------------------------------------ using namespace std; using namespace NXOpen; using namespace NXOpen::BlockStyler; // 哈希函数对象 struct EdgePtrHash { size_t operator()(Edge* edge) const { return std::hash<int>()(edge->Tag()); } }; // 相等比较函数对象 struct EdgePtrEqual { bool operator()(Edge* lhs, Edge* rhs) const { return lhs->Tag() == rhs->Tag(); } }; using EdgeSet = std::unordered_set<Edge*, EdgePtrHash, EdgePtrEqual>; class DllExport RuledFaces { // class members public: static Session* theSession; static UI* theUI; RuledFaces(); ~RuledFaces(); NXOpen::BlockStyler::BlockDialog::DialogResponse Launch(); void print(const NXString&); void print(const string&); void print(const char*); //----------------------- BlockStyler Callback Prototypes --------------------- // The following member function prototypes define the callbacks // specified in your BlockStyler dialog. The empty implementation // of these prototypes is provided in the RuledFaces.cpp file. // You are REQUIRED to write the implementation for these functions. //------------------------------------------------------------------------------ void initialize_cb(); void dialogShown_cb(); int apply_cb(); int ok_cb(); int update_cb(NXOpen::BlockStyler::UIBlock* block); PropertyList* GetBlockProperties(const char* blockID); private: Part* workPart; NXMessageBox* mb; ListingWindow* lw; LogFile* lf; const char* theDlxFileName; NXOpen::BlockStyler::BlockDialog* theDialog; NXOpen::BlockStyler::Group* group0; NXOpen::BlockStyler::ObjectColorPicker* colorPicker0;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* colorPicker01;// Block type: Color Picker NXOpen::BlockStyler::BodyCollector* bodySelect0;// Block type: Body Collector NXOpen::BlockStyler::Separator* separator0;// Block type: Separator NXOpen::BlockStyler::Group* group;// Block type: Group NXOpen::BlockStyler::FaceCollector* face_select0;// Block type: Face Collector NXOpen::BlockStyler::FaceCollector* face_select01;// Block type: Face Collector NXOpen::BlockStyler::Separator* separator01;// Block type: Separator NXOpen::BlockStyler::ObjectColorPicker* colorPicker02;// Block type: Color Picker private: int _fixed_face_color, _transitional_face_color, _transitioned_face_color; void do_it(); Features::Ruled* doCreateRuledFace(Edge* edge1, Edge* edge2); bool doReplaceFace(Face* origin_face, Face* replace_face); bool isEqualXY(const Point3d& a1, const Point3d& a2, const Point3d& b1, const Point3d& b2, double eps); bool ifContainEqulaEdge(Edge* origin_edge, EdgeSet& edge_set, Edge*& res_edge); vector<Body*> getBodies(); void getFixedAndTransitionalFaces(const vector<Body*>& bodies, vector<Face*>& fixed_faces, vector<Face*>& transitional_faces); EdgeSet getFixedEdgeSet(const vector<Face*>& fixed_faces); bool tryReverseRuledDirection(Features::Ruled* ruled_face); }; #endif //RuledFaces_H_INCLUDED
最新发布
08-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值