https://cn.vjudge.net/problem/1365218/origin

题意 一条直线上有n棵树 每棵树上有ci只鸟 在一棵树底下召唤一只鸟的魔法代价是costi 每召唤一只鸟,魔法上限会增加B 从一棵树走到另一棵树,会增加魔法X 一开始的魔法和魔法上限都是W 问最多能够召唤的鸟的个数

显然这是一道DP题

用dp[i][j]来表示到j这个树下选到j只鸟可以获得的最大能量值

很容易得出dp状态转移方程dp[i][j] = max(dp[i][j],dp[i][j - 1] - cost,dp[i - 1][j - 1] - cost);

由于每棵树上的鸟数量有限制,需要多一重大小为c的循环,但是因为∑c为1e3,三重循环的时间复杂度事实上仅为O(n * sum(c))可以接受

初始状态是dp[i][0] = W; 其他的状态为-1表示无法到达

进而可以考虑到每棵树事实上是一个多重背包,在dp的过程中考虑二进制优化,以及将dp开成滚动数组来优化空间

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 1e3 + ;
const int maxm = 1e4 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,tmp,K;
LL W,B,X;
LL dp[][maxm];
PIL b[maxn];
vector<PIL>P;
int C[maxn];
int main()
{
scanf("%d%lld%lld%lld",&N,&W,&B,&X);
int sum = ;
Mem(dp,-);
For(i,,N) Sca(C[i]);
For(i,,N){
Mem(dp[i & ],-);
dp[i & ][] = W;
int c = C[i]; LL cost;
scanf("%lld",&cost);
P.clear();
P.pb(mp(,));
sum += c;
//cout << sum <<endl;
tmp = ;
for(int j = ; j <= c; j <<= ){
P.pb(mp(j,cost * j));
c -= j;
}
if(c) P.pb(mp(c,cost * c));
for(int k = ; k < P.size(); k ++){
PIL u = P[k];
for(int j = sum;j >= u.fi ; j--){
if(dp[i & ][j - u.fi] >= u.se) dp[i & ][j] = max(dp[i & ][j],dp[i & ][j - u.fi] - u.se);
if(dp[i - & ][j - u.fi] == -) continue;
LL t = min(dp[i - & ][j - u.fi] + X,W + B * (j - u.fi));
if(t >= u.se) dp[i & ][j] = max(dp[i & ][j],t - u.se);
}
}
}
int ans;
_For(i,sum,){
if(dp[N & ][i] != -){
ans = i;
break;
}
}
Pri(ans);
return ;
}

CodeForces922E DP//多重背包的二进制优化的更多相关文章

  1. 动态规划:HDU2844-Coins(多重背包的二进制优化)

    Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  2. HDU 1059(多重背包加二进制优化)

    http://acm.hdu.edu.cn/showproblem.php?pid=1059 Dividing Time Limit: 2000/1000 MS (Java/Others)    Me ...

  3. dp之多重背包(二进制优化)

    void solve(int v,int w,int c){    int count=0;    for(int k=1;k<=c;k<<=1)    {        val[c ...

  4. POJ 1276 Cash Machine(多重背包的二进制优化)

    题目网址:http://poj.org/problem?id=1276 思路: 很明显是多重背包,把总金额看作是背包的容量. 刚开始是想把单个金额当做一个物品,用三层循环来 转换成01背包来做.T了… ...

  5. HDU-2844 Coins 多重背包 物品数量二进制优化

    题目链接:https://cn.vjudge.net/problem/HDU-2844 题意 给你一些不同价值和一定数量n的硬币. 求用这些硬币可以组合成价值在[1 , m]之间的有多少. 思路 多重 ...

  6. 多重背包的二进制优化——DP

    #include<cstdio> #include<cstring> #include<algorithm> #define LL long long using ...

  7. HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化)

    HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化) 题意分析 首先C表示测试数据的组数,然后给出经费的金额和大米的种类.接着是每袋大米的 ...

  8. hdu1059&poj1014 Dividing (dp,多重背包的二分优化)

    Problem Description Marsha and Bill own a collection of marbles. They want to split the collection a ...

  9. HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)

    HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化) 题意分析 先把每种硬币按照二进制拆分好,然后做01背包即可.需要注意的是本题只需要求解可以凑出几种金钱的价格,而不需要输出种数 ...

随机推荐

  1. codeforces158D

    Ice Sculptures CodeForces - 158D The Berland University is preparing to celebrate the 256-th anniver ...

  2. Base64 总结

    Base64编码是解决一些无法打印的字符无法显示的问题,将8位的ascii编码转换为6位的表示64个可见字符的算法. 具体而言,首先将编码每三个分成一组,将三个字符转换为总长为24位的二进制 数字,将 ...

  3. FFmpeg 将YUV数据转RGB

    只要开始初始化一次,结束后释放就好,中间可以循环转码 AVFrame *m_pFrameRGB,*m_pFrameYUV; uint8_t *m_rgbBuffer,*m_yuvBuffer; str ...

  4. Scrapy爬取伯乐在线文章

    首先搭建虚拟环境,创建工程 scrapy startproject ArticleSpider cd ArticleSpider scrapy genspider jobbole blog.jobbo ...

  5. scrapy爬取知乎问答

    登陆 参考 https://github.com/zkqiang/Zhihu-Login # -*- coding: utf-8 -*- import scrapy import time impor ...

  6. CODEFORCES掉RATING记 #5

    ​ 比赛:Codeforces Round #429 (Div. 2) ​ 时间:2017.8.1晚 这次感觉状态不好,就去打div2了 ​ A:有\(26\)种颜色的气球,每种的数量不一样,你要把这 ...

  7. 「CodeForces - 50C 」Happy Farm 5 (几何)

    BUPT 2017 summer training (16) #2B 题意 有一些二维直角坐标系上的整数坐标的点,找出严格包含这些点的只能八个方向走出来步数最少的路径,输出最少步数. 题解 这题要求严 ...

  8. python学习日记(函数进阶)

    命名空间 内置命名空间 存放了python解释器为我们提供的名字:print,input...等等,他们都是我们熟悉的,拿过来就可以用的方法. 内置的名字在启动解释器(程序运行前)的时候被加载在内存里 ...

  9. 给 Haproxy 创建日志文件

    背景介绍:默认下的Haproxy配置是不会生成日志文件的,而无运行日志,无法确定系统运行是否流畅,无法提起预判可能发生的故障 创建Haproxy日志文件的步骤如下vi /etc/rsyslog.con ...

  10. HDU 6319 Problem A. Ascending Rating(单调队列)

    要求一个区间内的最大值和每次数过去最大值更新的次数,然后求每次的这个值异或 i 的总和. 这个序列一共有n个数,前k个直接给出来,从k+1到n个数用公式计算出来. 因为要最大值,所以就要用到单调队列, ...