B. Checkout Assistant 01背包变形

http://codeforces.com/problemset/problem/19/B

对于每个物品,能偷多ti个,那么先让ti + 1, 表示选了这个东西后,其实就是选了ti + 1个了。那么只需要选出>=n个即可。

一开始的时候想不到ti + 1,一直不知道能多选ti个后,本来是选了多少个。

#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>
const int maxn = 2e3 + 20;
int w[maxn];
int val[maxn];
LL dp[2000 * 2000 + 20];
void work() {
    int n;
    cin >> n;
    int sum = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> w[i] >> val[i];
        w[i]++;
        w[i] = min(w[i], 2000);
        sum += w[i];
    }
    for (int i = 0; i <= 2000 * 2000 - 2; ++i) {
        dp[i] = 1e17L;
    }
    dp[0] = 0;
    sum = min(4000, sum);
    for (int i = 1; i <= n; ++i) {
        for (int j = sum; j >= w[i]; --j) {
            dp[j] = min(dp[j], dp[j - w[i]] + val[i]);
        }
    }
    LL ans = 1e17L;
    for (int i = n; i <= sum; ++i) {
        ans = min(ans, dp[i]);
    }
    cout << ans << endl;
}

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

写了一个超时的二维费用背包

dp[i][j]表示前n个数选出i个,有j个可以免费拿的情况。

直接超时。

#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>
const int maxn = 2e3 + 20;
LL dp[maxn][maxn];
int ti[maxn];
int cost[maxn];

void work() {
    int n;
    cin >> n;
    int sum = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> ti[i] >> cost[i];
        sum += ti[i];
    }
    for (int i = 0; i <= 2000 + 2; ++i) {
        for (int j = 0; j <= 2000 + 2; ++j) {
            dp[i][j] = 1e17L;
        }
    }
    dp[0][0] = 0;
    sum = min(2000, sum);
    for (int i = 1; i <= n; ++i) {
        for (int j = i; j >= 1; --j) {
            for (int k = sum; k >= ti[i]; --k) {
                dp[j][k] = min(dp[j][k], dp[j - 1][k - ti[i]] + cost[i]);
            }
        }
    }
    LL ans = 1e17L;
    for (int i = 1; i <= n; ++i) {
        for (int j = sum; j >= 0; --j) {
            dp[i][j] = min(dp[i][j], dp[i][j + 1]);
        }
    }
    for (int i = 1; i <= n; ++i) {
        ans = min(ans, dp[i][n - i]);
    }
    cout << ans << endl;
//    cout << dp[3][5] << endl;
}

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

时间: 2024-11-05 09:33:58

B. Checkout Assistant 01背包变形的相关文章

HDU 2955 Robberies --01背包变形

这题有些巧妙,看了别人的题解才知道做的. 因为按常规思路的话,背包容量为浮点数,,不好存储,且不能直接相加,所以换一种思路,将背包容量与价值互换,即令各银行总值为背包容量,逃跑概率(1-P)为价值,即转化为01背包问题. 此时dp[v]表示抢劫到v块钱成功逃跑的概率,概率相乘. 最后从大到小枚举v,找出概率大于逃跑概率的最大v值,即为最大抢劫的金额. 代码: #include <iostream> #include <cstdio> #include <cstring>

codeforce Gym 101102A Coins (01背包变形)

01背包变形,注意dp过程的时候就需要取膜,否则会出错. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXW 15005 #define N 155 #define LL long long #define MOD 1000000007 int w1[N],w2[N]; LL dp1[MAXW],dp2[MAXW]; int main(

Wikioi 1025 01背包变形

这题多加了菜品必选编号,所以刚开始不知道怎么写,原来就把必选的处理下就行了,因为有重复,但是相同的价值与价格都一样,所以这里就直接挑出来就行了. 把不是必选的在里面用dp即可,dp之前也要把重复的舍去. 因为总价格容量为浮点数,所以先乘以10变成整数就可以用01背包了. #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <deque&

codeforces 742D Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses ——(01背包变形)

题意:给你若干个集合,每个集合内的物品要么选任意一个,要么所有都选,求最后在背包能容纳的范围下最大的价值. 分析:对于每个并查集,从上到下滚动维护即可,其实就是一个01背包= =. 代码如下: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <vector> 5 using namespace std; 6 const int N = 1000 + 5;

POJ 3093 Margaritas on the River Walk (0-1背包变形)

这题目的思路很巧妙,什么情况下剩下的所有物品都放不下呢?就是当前剩余物品中最小的那个也放不下.所以,先把物品按照容量从小到大排序,依次枚举当前背包为放不下的最小物品的情况. 对于当前物品i,必有1到i-1的所有物品都放进去,这时候比i大的物品谁放谁不放是不确定的.转换成0-1背包问题:把前i-1个物品都放进去以后,得到空间为tsum - sum[i-1](前缀和)的包,只要从第i+1到第n个物品中拿出一个方案填充这个包使得剩余体积小于第i个物品的体积就可以了,把总方案数累加就是结果! 注意特殊情

HDU 2639 Bone Collector II(01背包变形【第K大最优解】)

Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4739    Accepted Submission(s): 2470 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took pa

soj 2222 01背包变形

背景:wa~Tl~看来背包还是很欠缺啊~ 思路1(1500ms):变形的01背包.把题目改为:选择一组HP和大于等于所需血量且这组物品的分数之和最小,即可.这里把HP看做cost,score看做weight.但是这个题有个特点是最后选择HP必须大于等于k,容易想到,最多我们会有k+10000(10000为单个物品的最大HP值)的HP值,所以我们有这样的转移方程: for i 0....n for j K+10000....cost[i] F[j]=min(F[j],F[j-cost[i]]+we

poj 2184 Cow Exhibition(dp之01背包变形)

Description "Fat and docile, big and dumb, they look so stupid, they aren't much fun..." - Cows with Guns by Dana Lyons The cows want to prove to the public that they are both smart and fun. In order to do this, Bessie has organized an exhibitio

hdu(5389)——Zero Escape(01背包变形)

啊,这是一道挺不错的动态规划的题目呢. 一开始我们并没有找出规律,后来队友突然喊了一句:"dp啊!" 顿时人生豁然开朗了... 于是她很神奇的推出了转移方程,然后再共同查错下,a出了这道题,真是佩服这人的高智商啊 题意: 首先n,代表的是n个人,然后是A,B,分别代表两个门的值. 然后第二行给出了n个人的价值,问你要使这n个人全部进入门中(可以是A,B,或是其中的一扇门),总共有几种方法. 但是要注意这里的价值并不是仅仅加起来就好了,这里是要把它加起来直到为一个个位数. 思路: 定义: