USACO 2.2 Subset Numbers

本文详细阐述了如何使用动态规划解决背包问题,并提供了经典代码实现。通过实例分析,揭示了01背包问题的核心思路和算法优化技巧。

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

        这道题第一个想到的是采用DFS,果不其然倒在了超时下。苦思之后无解,就搜索了一下这道题的题解,发现大家都提示说要用动态规划来做。


        最终采用了一维的DP。问题的关键是,建立一个数组,这个数组存放每种背包容量的数量。

        比如说{1,2,3}这个组合,由于我们的目标容量是3,所以需要存放加起来为0、1、2、3这四种容量的组合数量。下面的表格是一个示例,其中第一列是容量,作为数组的标号,第二列是这种容量的数目,作为数组的值,第三列是具体的组合。

VN 
01{}
11{1}
21{2}
32{1,2}, {3}


        这是一道典型的01背包的题目,所以就直接贴上代码了:

        这边还有个暗坑,组合数量可能超过int的范围,图省事我就改成用unsigned long型存放了。

#include <iostream>
#include <fstream>
using namespace std;

const int MAXN = 39;
int N;
int t;
unsigned long f[MAXN*MAXN];

int main()
{
    ifstream fin ("subset.in");
    ofstream fout ("subset.out");
    int i, j;

    fin >> N;
    t = (1+N)*N;
    if (t % 4) {
        fout << 0 << endl;
        return 0;
    }
    t /= 4;

    f[0] = 1;
    for (i = 1; i <= N; i++)<span style="white-space:pre">		</span>//i为物品重量
        for (j = t; j >= i; j--)<span style="white-space:pre">	</span>//j为背包容量
            f[j] += f[j-i];

    fout << f[t]/2 << endl;

    return 0;
}


        看了一下官方解,官方给出了二维和一维这两种解法,逻辑很清晰,很值得学习。


        闲话时间。做了这道题之后,发现自己对一些经典的——比如这次的动态规划——算法不是很熟悉。如果接下来有时间的话,可能会写些关于背包问题和动态规划的理解吧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值