E. The Values You Can Make 背包,同时DP

http://codeforces.com/problemset/problem/688/E

题目需要在n个数中找出一个集合,使得这个集合的和为val,然后问这些所有集合,能产生多少个不同的和值。

题解是直接两个同时dp,设dp[j][h]表示主集合的和为j,能否产生h这个数字。

把他们看作是两个集合,对于每个数,都可以放在第一个集合,或者放在第一个集合后,再放入第二个集合。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 500 + 20;
bool dp[maxn][maxn];
set<int>ans;
void work() {
    int n, k;
    cin >> n >> k;
    dp[0][0] = true;
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        for (int j = k; j >= 0; --j) {
            for (int h = j; h >= 0; --h) {
                if (j >= x) { //第一个集合
                    dp[j][h] = dp[j][h] || dp[j - x][h];
                }
//                if (h >= x) {
//                    dp[j][h] = dp[j][h] || dp[j][h - x];
//                }
                if (h >= x && j >= x) {
                    dp[j][h] = dp[j][h] || dp[j - x][h - x];
                }

            }
        }
    }
//    cout << dp[5][0] << endl;
    for (int i = 0; i <= k; ++i) {
        if (dp[k][i] == false) continue;
        ans.insert(i);
    }
    cout << ans.size() << endl;
    for (set<int> :: iterator it = ans.begin(); it != ans.end(); ++it) {
        cout << *it << " ";
    }
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}

时间: 2024-08-10 05:16:37

E. The Values You Can Make 背包,同时DP的相关文章

hdu 1011 Starship Troopers (依赖背包 树形dp)

题目: 链接:点击打开链接 题意: n个房间组成一棵树,你有m个战队,从1号房间开始依次clear每个房间,在每个房间需要花费的战队个数是bugs/20,得到的价值是the possibility of capturing a brain,求最大的价值. 算法: 树形dp,有依赖的背包问题.(依次clear每个房间) 思路: 状态转移dp[i][j]表示根结点为i时(房间i)花费j个战队能够得到的最大价值(捕捉到一个brain最大的可能值).递归求出每个根结点处的最大值,最后dp[1][m]就是

hdu 1561 The more, The Better (依赖背包 树形dp)

题目: 链接:点击打开链接 题意: 非常明显的依赖背包. 思路: dp[i][j]表示以i为根结点时攻击j个城堡得到的最大值.(以i为根的子树选择j个点所能达到的最优值) dp[root][j] = max(dp[root][j],dp[root][k]+dp[u][j-k]); u递归根结点,root当前根结点,每一个城堡之间的依赖关系形成森林.应该转化为树.再树形dp.仅仅需添加一个根结点即可.m++. 代码: #include<iostream> #include<cstdio&g

poj3624 01背包入门 dp+滚动数组

poj3624 01背包 dp+滚动数组 Charm Bracelet Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25458   Accepted: 11455 Description Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the bes

[Uva12563] Jin Ge Jin Qu hao (完全背包,dp)

题目链接:https://vjudge.net/problem/UVA-12563 题意:n首歌要在m-1的时间内挑k首唱,现在希望在k尽可能大的情况下,时间尽可能长地唱.问最后最大k+1多大,最长时间+678多长. 普通完全背包,附加额外记一维记录歌曲个数.先判断当个数相同的时候,仅更新时长,否则两个都更新. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 55; 5 const int maxm

洛谷——背包型dp

1.P1417 烹调方案 题目背景 由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~ gw还是会做饭的,于是拿出了储藏的食物准备填饱肚子.gw希望能在T时间内做出最美味的食物,但是这些食物美味程度的计算方式比较奇葩,于是绝望的gw只好求助于你了. 题目描述 一共有n件食材,每件食材有三个属性,ai,bi和ci,如果在t时刻完成第i样食材则得到ai-t*bi的美味指数,用第i件食材做饭要花去c

HDU 2955 Robberies 背包概率DP

A - Robberies Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2955 Appoint description: Description The aspiring Roy the Robber has seen a lot of American movies, and knows that the bad guys usu

采药---0-1背包型dp

题目描述 Description 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给他出了一个难题.医师把他带到一个到处都是草药的山洞里对他说:"孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值.我会给你一段时间,在这段时间里,你可以采到一些草药.如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大." 如果你是辰辰,你能完成这个任务吗? 输入描述 Input Descriptio

NOJ 1860 保研(0/1背包概率dp)

保研 时间限制(普通/Java):1000MS/3000MS         运行内存限制:65536KByte 总提交:171          测试通过:40 题目描述 对于一些名校而言,保研不仅可以由学校推免,也可以由学生自己向希望保研的学校提出申请,这个过程有点类似于外国学生向学校提交简历等待Offer的过程.但是,投递申请需要亲自去相应学校的研招办递交材料,这就需要一些成本(比如路费等),且每个院校都有自己的录取成功率.现在,请在总成本不超过限制的情况下,求出最大的成功率. 输入 输入

各种背包的dp刷题板

[p1332][NYOJ skiing] 滑雪  (dp+搜索) [p1312] [vjios1448 路灯改建计划] 关灯问题 (背包预处理的分组背包) f[i][j]表示给把前i个灯分为j组可以获得的最大照明度 g[i][j]表示第i盏灯到第j盏灯分为一组在满足前提条件下的最大照明度 在预处理g[i][j]的i循环内,用一个d[x][y]数组先预处理出:[i,x]内所有编号的灯总耗电量y时的最大照明度(y的上限显然为(n-i+1)*t)然后g[i][j]=d[j][(j-i+1)*t]即可得