【dp】 AreYouBusy

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3535

题意: 多组背包, 0类型为为至少去1样, 1为至多取1样, 2 为随意。

如果将2类型 再添加一组数据 (0, 0), 则可转换为0类型, 即0,1 背包问题, 1类型为经典分组背包。

/***Good Luck***/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <functional>
#include <cmath>
#include <numeric>

#define Zero(a) memset(a, 0, sizeof(a))
#define Neg(a)  memset(a, -1, sizeof(a))
#define All(a) a.begin(), a.end()
#define PB push_back
#define inf 0x3f3f3f3f
#define inf2 0x7fffffffffffffff
#define ll long long
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
void get_val(int &a) {
    int value = 0, s = 1;
    char c;
    while ((c = getchar()) == ‘ ‘ || c == ‘\n‘);
    if (c == ‘-‘) s = -s; else value = c - 48;
    while ((c = getchar()) >= ‘0‘ && c <= ‘9‘)
        value = value * 10 + c - 48;
    a = s * value;
}
const int maxn = 110;
int n, t;
int dp[maxn][maxn];
int C[maxn][maxn];
int G[maxn][maxn];
int TE[maxn];
int N1[maxn];

int main() {
    //freopen("data.out", "w", stdout);
    //freopen("data.in", "r", stdin);
    //cin.sync_with_stdio(false);
    while (cin >> n >> t){
        for (int i = 1; i < maxn; ++i)
        for (int j = 0; j < maxn; ++j)
            dp[i][j] = -inf;
        Zero(dp[0]);
        int n1, te;
        for (int i = 1; i <= n; ++i) {
            scanf("%d%d", &n1, &te);
            for (int j = 1; j <= n1; ++j) {
                scanf("%d%d", C[i] + j, G[i] + j);
            }
            if (te != 0) {// 情况一和情况三相似, 在情况三中添加一组0, 0 便可表示任意取
                n1++;     // 及可取可不取。
                C[i][n1] = 0;
                G[i][n1] = 0;
            }
            TE[i] = te;
            N1[i] = n1;
        }
        for (int i = 1; i <= n; ++i) {
            if (TE[i] == 0) {
                for (int ii = 1; ii <= N1[i]; ++ii) //dp[i][v] = max(dp[i][v], dp[i][v - C[i][ii]] + G[i][ii],dp[i - 1][v - C[i][ii]] + G[i][ii])
                for (int v = t; v >= C[i][ii]; --v) {
                    dp[i][v] = max(dp[i][v], dp[i][v - C[i][ii]] + G[i][ii]);
                    dp[i][v] = max(dp[i][v], dp[i - 1][v - C[i][ii]] + G[i][ii]);
                }
            }
            else if (TE[i] == 1) {
                for (int v = t; v >= 0; v--)
                for (int ii = 1; ii <= N1[i]; ++ii)
                if (v >= C[i][ii])
                    dp[i][v] = max(dp[i][v], dp[i - 1][v - C[i][ii]] + G[i][ii]);
            }
            else {
                for (int ii = 1; ii <= N1[i]; ++ii)
                for (int v = t; v >= C[i][ii]; --v) {
                    dp[i][v] = max(dp[i][v], dp[i][v - C[i][ii]] + G[i][ii]);
                    dp[i][v] = max(dp[i][v], dp[i - 1][v - C[i][ii]] + G[i][ii]);
                }
            }
        }
        if (dp[n][t] >= 0)
        printf("%d\n", dp[n][t]);
        else printf("-1\n");
    }
    return 0;
}
时间: 2024-08-24 10:06:47

【dp】 AreYouBusy的相关文章

hdoj 2391 Filthy Rich 【DP】

题目大意:有个二维数组,你从(0,0)出发,最终到(n,m), 在这个二维数组中,每个位置dp[i][j]都有一定量的黄金,你可以拾取,问你最多能失去多少,并且,你的方向有下,右, 斜向下三个方向: 策略:就是每一个都加上它的上方向与左方向的最大值,这样到最后就是最大值.详情见代码 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2391 代码: #include<stdio.h> #include<string.h> int dp[1

HDOJ1176 免费馅饼 【DP】+【经典数塔】

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 23986    Accepted Submission(s): 8093 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的1

nyoj 325 zb的生日 【DP】||【DFS】

两种方法: 第一种:将总数一半当做背包,用总数-2*最多能装的数目就是所求: 第二种:深搜: zb的生日 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 今天是阴历七月初五,acm队员zb的生日.zb正在和C小加.never在武汉集训.他想给这两位兄弟买点什么庆祝生日,经过调查,zb发现C小加和never都很喜欢吃西瓜,而且一吃就是一堆的那种,zb立刻下定决心买了一堆西瓜.当他准备把西瓜送给C小加和never的时候,遇到了一个难题,never和C小加不在一块住,只能

HDOJ4540 威威猫系列故事——打地鼠 【DP】

威威猫系列故事--打地鼠 Time Limit: 300/100 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1445    Accepted Submission(s): 713 Problem Description 威威猫最近不务正业,每天沉迷于游戏"打地鼠". 每当朋友们劝他别太着迷游戏,应该好好工作的时候,他总是说,我是威威猫,猫打老鼠就是我的工作! 无话

NYOJ16 矩形嵌套 【DP】

矩形嵌套 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度).例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中.你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内. 输入 第一行是一个正正数N(0<N<10),表示测试数据组数, 每组

hdoj 2046 骨牌铺方格 【DP】+【斐波那契】

dp果然不是好学的... 第n个,即2*n时,可由第n-1个的竖直排列再加一个,和第n-2个中横着排两个 所以f(n) = 1×f(n-1) + 1×f(n-2): 骨牌铺方格 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 28412    Accepted Submission(s): 13771 Problem Descripti

【题解】【数组】【DP】【Codility】MaxSliceSum &amp; MaxDoubleSliceSum

MaxSliceSum 5 -7 3 5 -2 4 -1 这个数组的最大子串是3 5 -2 4 Complexity: expected worst-case time complexity is O(N); expected worst-case space complexity is O(1), beyond input storage (not counting the storage required for input arguments). 思路 O(n) 的解法的关键,是把原来求最

[HDOJ - 5282] Senior&#39;s String 【DP】

题目链接:BZOJ - 5282 题目分析 LCS 就是用经典的 O(n^2) DP 解决,f[i][j] 表示 x 串前 i 个字符与 y 串前 j 个字符的 LCS 长度. f[i][j] = max(f[i - 1][j], f[i][j - 1]); if (x[i] == y[j]) f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1); 然后再设置一个状态 g[i][j], 表示 x 串的前 i 个字符中,有多少个长为 f[i][j] 的子序列同时也

HDU2391 Filthy Rich 【DP】

Filthy Rich Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1793    Accepted Submission(s): 815 Problem Description They say that in Phrygia, the streets are paved with gold. You're currently