[背包DP] 洛谷相关题目整理与练习(74题-)

题目

以背包为标签,搜出了这么多题,按难度排序,一道一道做:
(*):下面有提到

TODO 题目 难度 备忘录
AC 采药 普及- 01背包模板
AC 开心的金明 普及- 01背包模板
AC 小A点菜 普及- 背包方案数问题
AC NASA的食物计划 普及- 简单的二维费用背包
AC 疯狂的采药 普及- 完全背包问题
AC 通天之分组背包 普及- 分组背包模板
AC 神奇的四次方数 普及- 简单的判断型完全背包(*)
AC 最大约数和 普及- 简单的01背包+预处理
AC A+B Problem(再升级) 普及- 完全背包方法数(*)
AC [HAOI2012]音量调节 普及- 刷表法的多阶段决策问题
AC 小书童——刷题大军 普及- 两个01背包
AC 三角形牧场 提高- 01背包,已知推未知的状压DP
AC 搭配购买 提高- 连通块的01背包(*)
AC 集合 Subset Sums 提高- 二维费用方法数(*)
积木城堡 提高-
投资的最大效益 提高-
魔术棋子 提高-
机器分配 提高-
yyy2015c01的U盘 提高-
[AHOI2001]质数和分解 提高-
邮票 Stamps 提高-
珍珠配对 提高-
跨河 提高-
买干草 提高-
牛飞盘队 提高-
奶酪塔 提高-
购买巧克力 提高-
AC 金明的预算方案 提高 简单的依赖背包,靠枚举
AC 烹调方案 提高 价值变换的背包
选学霸 提高
哞哞哞Mooo Moo 提高
虫洞Wormholes 提高
牛的过山车 提高
股票市场 提高
拖拉机Tractor 提高
赛斯石(赛后强化版) 提高
不开心的金明 提高
AC 垃圾陷阱 省选- 复杂二维费用,状态定义与转移问题
AC 多米诺骨牌 省选- 抽象出来凑差值的01背包
宝物筛选 省选-
飞扬的小鸟 省选-
产品加工 省选-
计算器写作文 省选-
豪华游轮 省选-
商店购物 省选-
最少的硬币 省选-
挤奶的时间 省选-
小Q的棋盘 省选-
Eden 的新背包问题 省选-
挂饰 省选-
消失之物 省选-
采摘毒瘤 省选-
小A的时钟 省选
语文-理理思维 省选
梦幻岛宝珠 省选
星空 省选
魔兽地图 省选
粉刷匠 省选
基因匹配 省选
苹果树 NOI+
付公主的背包 NOI+
秘密袭击coat NOI+

PASS掉的其它的题:
(大概就是很简单或者重复的题目类型,有限的人生就不浪费在这些水题上了)

TODO 题目 难度 备忘录
PASS 混合牛奶 普及- 01背包模板
PASS 扑克牌 普及- 数学题
PASS 总分 Score Inflation 普及- USACO的01背包模板
AC L国的战斗之间谍 普及- 简单的二维费用
PASS kkksc03考前临时抱佛脚 普及- 不像是背包
PASS Bessie的体重问题 普及- 01背包模板
PASS 手链 普及- 01背包模板
PASS 干草出售 普及- 01背包模板
AC 榨取kkksc03 提高- 简单的二维费用
PASS 精卫填海 提高- 简单的01背包
PASS 樱花 提高- 混合背包

理解

神奇的四次方数

LP1679
刚开始以为是01背包,然后就WA了,然后发现题目并没有对某一物品的使用次数进行限制。所以这里要注意,背包问题读题时的一个问题,就是应该抠字眼扣清楚每个物品使用次数,来区分各种背包模型。

A+B Problem(再升级)

1.给定一个正整数n,求将其分解成若干个素数之和的方案总数。
这题都能爆int你敢信?。。
当n=1000时,方案数为48278613741845757。
所以长点心。。这种很迷的数学题要经常记得用longlong。


2.简单的验证素数方法:

bool flag = true;
        for (int i = 2; i <= trunc(sqrt(num)); i++)
            if (num % i == 0) flag = false;
// trunc:小数去尾并变成int
[HAOI2012]音量调节

LP1877
本题用的是刷表法,用d[i][j]来更新d[i+1][j+v]和d[i+1][j-v]。由于决策往前往后的都用,不能确定滚动数组的枚举顺序。硬要用滚动数组的话,可以用一个二维的滚动数组

搭配购买

P1455,连通块01背包,代码放这以供参考。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int maxn = 10000 + 10;
vector<int> edge[maxn];
int n, m, c, v[maxn], w[maxn], cc, nv[maxn], nw[maxn], vis[maxn], d[maxn];

void dfs(int u, int cnt) {
    nv[cnt] += v[u];
    nw[cnt] += w[u];
    vis[u] = 1;
    for(vector<int>::iterator iter = edge[u].begin(); iter!=edge[u].end(); ++iter)
        if (!vis[*iter]) {
            dfs(*iter, cnt);
        }
}

int main() {
    scanf("%d%d%d", &n, &m, &c);
    _rep(i, 1, n) scanf("%d%d", &v[i], &w[i]);
    int u, v;
    _for(i, 0, m) {
        scanf("%d%d", &u, &v);
        edge[u].push_back(v);
        edge[v].push_back(u);
    }

    cc = 0;
    _rep(i, 1, n)
        if (!vis[i])
            dfs(i, cc++);

    _for(i, 0, cc)
        for (int j = c; j >= nv[i]; j--)
            d[j] = max(d[j], d[j - nv[i]] + nw[i]);

    printf("%d\n", d[c]);

    return 0;
}
集合

LP1466
小题的细节问题:即便是这样简单题,也应该写对拍。
错误代码:(n=5时,返回1)

int main() {
    scanf("%d", &n);
    d[0][0] = 1;
    int s = n * (n + 1) / 4;
    _rep(i, 1, n)
        for (int j = s; j >= 0; j--)
            for (int k = s; k >= 0; k--) {
                if (j >= i)
                    d[j][k] += d[j - i][k];
                if (k >= i)
                    d[j][k] += d[j][k - i];
            }

    printf("%lld\n", d[s][s] / 2);
    return 0;
}

正确代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int maxn = 1000 + 10;
int n;
ll d[maxn][maxn];

int main() {
    scanf("%d", &n);
    d[0][0] = 1;
    int s = n * (n + 1) / 4;
    if (n*(n + 1) == s * 4) {
        _rep(i, 1, n)
            for (int j = s; j >= 0; j--)
                for (int k = s; k >= 0; k--) {
                    if (j >= i)
                        d[j][k] += d[j - i][k];
                    if (k >= i)
                        d[j][k] += d[j][k - i];
                }

        printf("%lld\n", d[s][s] / 2);
    }
    else {
        printf("0\n");   // 无法成功二分,自然方案数为0
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/icecab/article/details/81141388
今日推荐