1005. Stone Pile 背包问题 动态规划

2023-12-25 12:38

本文主要是介绍1005. Stone Pile 背包问题 动态规划,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


You have a number of stones with known weights w1, …, wn. Write a program that will rearrange the stones into two piles such that weight difference between the piles is minimal.

Input

Input contains the number of stones n (1 ≤ n ≤ 20) and weights of the stones w1, …, wn (integers, 1 ≤ wi ≤ 100000) delimited by white spaces.

Output

Your program should output a number representing the minimal possible weight difference between stone piles.

Sample

inputoutput
5
5 8 13 27 14
3


这是一个背包问题,发现背包问题自己已经忘记的差不多了,所以决定重新弄清楚。

有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。
求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
基础的是01背包问题,特点是每种物品仅有一件,可以选择放或不放。
f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大值。
f[i][v] = max{f[i-1][v],f[i-1][v-w[i]]+v[i]}
压缩为f[v] = max{f[v],f[v-w[i]]+v[i]}
将问题分解为“前i件物品放入容量为v的背包中”这个子问题,如果只考虑第i件物品放入问题,那么就
转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么文件转化为“前i-1件物品放入容量为
v的背包中”,价值为f[i-1][v];如果放第i件物品,问题就转化为“前i-1件物品放入剩下的容量为
v-w[i]的背包中”,此时能获得的最大价值就是f [i-1][v-w[i]]再加上通过放入第i件物品获得的价值v[i].


#include<iostream>
using namespace std;
#define  V 1500
unsigned int f[10][V];//全局变量,自动初始化为0
unsigned int weight[10];
unsigned int value[10];
#define  max(x,y)   (x)>(y)?(x):(y)
int main()
{
    
    int N,M;
    cin>>N;//物品个数
    cin>>M;//背包容量
    for (int i=1;i<=N; i++)
    {
        cin>>weight[i]>>value[i];
    }
    for (int i=1; i<=N; i++){
        for (int j=1; j<=M; j++)
        {
            if (weight[i]<=j)
            {
                f[i][j]=max(f[i-1][j],f[i-1][j-weight[i]]+value[i]);
            }
            else
                f[i][j]=f[i-1][j];
        }
    }
    cout<<f[N][M]<<endl;//输出最优解
}
上面计算f[i][j]可以看出,在计算f[i][j]时只使用了f[i-1][0……j],没有使用其他子问题,因此在存储子问题的解时,
只存储f[i-1]子问题的解即可。这样可以用两个一维数组解决,一个存储子问题,一个存储正在解决的子问题.
f[j]=max(f[j],f[j-weight[i]]+value[i])

#include<iostream>

using namespacestd;

#define  V 1500

unsigned int f[V];//全局变量,自动初始化为0

unsigned int weight[10];

unsigned int value[10];

#define  max(x,y)   (x)>(y)?(x):(y)

int main()

{

    

    int N,M;

    cin>>N;//物品个数

    cin>>M;//背包容量

    for (int i=1;i<=N; i++)

    {

        cin>>weight[i]>>value[i];

    }

    for (int i=1; i<=N; i++){

        for (int j=M; j>=weight[i]; j--)

        {

            f[j]=max(f[j],f[j-weight[i]]+value[i]);

        }

    }

    

    cout<<f[M]<<endl;//输出最优解

}

而这个问题可以将M设置为total/2,即可。

#include<iostream>

#include <math.h>

using namespacestd;

#define  V 2500000

unsigned int f[V];//全局变量,自动初始化为0

unsigned int weight[22];

#define  max(x,y)   (x)>(y)?(x):(y)

int main()

{

    

    int N,M;

    cin>>N;//物品个数

    int total =0;

    for (int i=1;i<=N; i++)

    {

        cin>>weight[i];

        total = weight[i] + total;

    }

    M = total/2;

    for (int i=1; i<=N; i++){

        for (int j=M; j>=weight[i]; j--)

        {

            f[j]=max(f[j],f[j-weight[i]]+weight[i]);

        }

    }

    int temp = (total-f[M])-f[M];

    cout<<abs(temp)<<endl;//输出最优解

}



这篇关于1005. Stone Pile 背包问题 动态规划的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/535540

相关文章

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<

csu(背包的变形题)

题目链接 这是一道背包的变形题目。好题呀 题意:给n个怪物,m个人,每个人的魔法消耗和魔法伤害不同,求打死所有怪物所需的魔法 #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>//#include<u>#include<map

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监