题意:

给定n个块,编号从1到n,以及m个操作,初始时n个块是白色。

操作有2种形式:

1 ai xi : 从[1,ai]选xi个块,将这些块涂白。

2 ai xi:从[ai,n]选xi个块,将这些块涂白。

可以忽略某些操作且如果区间内没有足够的黑块(黑块用于涂白),则不能进行这个操作。

分析:

写写画画一看就知道这道题是一个背包问题。

“恰好装满背包”。

以下摘自题解:

本题难点在于正确处理两种操作,不妨假设只有一种操作,那么这种操作如果是1的话那么就把操作按照a从小到大排序,每次都尽量往最左边涂,如果是2的话则类似的涂到最右边,但本题两种操作都出现了。

先考虑第一问:

我们把所有的操作按类别区分开,假设所有的1操作尽量用上能从1涂到a格子,所有的2操作尽量用上能从b格子涂到n,假设a<b,那么答案显然是a+n-b+1。那么假设a>=b,那么假设1操作从1涂到x,那么2操作一定会从n尽量往左边涂,直到x为止。最后两边的总和就是答案。

由上不难想到一个DP,l[i][j]表示用了前i种1操作,从1涂到j的最小操作数,转移l[i][j]=min(l[i][j],l[i-1][j-ope[i].x]+1)(ope[i].x<=j<=ope[i].a),类似的,我们可以得到r[i][j]表示用2操作从j涂到n需要的最小操作数。dp复杂度O(n*m)。(这个背包也可以压缩一维,后面的l,r均为1维的状态)

那么我们倒着枚举涂色最大的数目,假设为k,这个数目必然由1操作贡献一部分,由2操作贡献一部分(也可能一个贡献全部,另一个为0),那么我们枚举1操作涂到了i,那么2操作必然涂到了n-(k-i)+1,如果l[i]和r[n-(k-i)+1]均有值,那么说明这个最大数目是可达的,即是第一问的答案。枚举复杂度O(n*n)。

再考虑第二问:

现在我们已经知道最大数目了,这个数目是由操作1和操作2一起贡献的,那么我们仍然可以枚举操作1涂到了i,那么操作2涂到了n-(ans-i)+1,如果l[i]和r[n-(k-i)+1]均有值,那么其和可以用来更新第二问的答案,最后第二问的答案为所有合法方案需操作数的最小值。枚举复杂度O(n*n)。

代码实现:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath> using namespace std;
const int maxn = ;
struct node{
int aa,cor;
node(){}
node(int _aa,int _cor){
aa = _aa; cor = _cor;
}
}x1[maxn],x2[maxn];
int n,m;
int dp1[maxn],dp2[maxn];
int sumx1,sumx2; bool cmp(const node &p,const node &q){
return p.aa < q.aa;
} int min(int a,int b)
{
return a<b?a:b;
} int main()
{
int cas,ta=;
scanf("%d",&cas);
while(cas--){
int i,j;
scanf("%d%d",&n,&m); sumx1 = sumx2 = ;
for(i=; i<m; i++){
int key,yy,z;
scanf("%d%d%d",&key,&yy,&z);
if(key == ){
x1[sumx1++] = node(yy,z);
}else{
x2[sumx2++] = node(n+-yy,z);
}
}
sort(x1+,x1+sumx1,cmp);
sort(x2+,x2+sumx2,cmp);
memset(dp1,0x3f,sizeof(dp1));
memset(dp2,0x3f,sizeof(dp2)); dp1[] = dp2[] = ;
for(i=; i<sumx1; i++){
for(j=x1[i].aa; j>=x1[i].cor; j--){
dp1[j] = min(dp1[j],dp1[j-x1[i].cor]+);
}
} for(i=; i<sumx2; i++){
for(j=x2[i].aa; j>=x2[i].cor; j--){
dp2[j] = min(dp2[j],dp2[j-x2[i].cor]+);
}
} int ans = ,anssum = ,tmp;
for(i=; i<=n; i++){
for(j=; j<=i; j++){
tmp = dp1[j] + dp2[i-j];
if(tmp <= m){
if(ans != i){
ans = i; anssum = tmp;
}else if(tmp < anssum){
anssum = tmp;
}
}
}
} printf("Case %d: %d %d\n",ta++,ans,anssum);
}
return ;
}

hdu 4381(背包变形)的更多相关文章

  1. HDU 1171 Big Event in HDU (多重背包变形)

    Big Event in HDU Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

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

    Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  3. 【01背包变形】Robberies HDU 2955

    http://acm.hdu.edu.cn/showproblem.php?pid=2955 [题意] 有一个强盗要去几个银行偷盗,他既想多抢点钱,又想尽量不被抓到.已知各个银行 的金钱数和被抓的概率 ...

  4. FZU 2214 Knapsack problem 01背包变形

    题目链接:Knapsack problem 大意:给出T组测试数据,每组给出n个物品和最大容量w.然后依次给出n个物品的价值和体积. 问,最多能盛的物品价值和是多少? 思路:01背包变形,因为w太大, ...

  5. Codeforces Round #214 (Div. 2) C. Dima and Salad (背包变形)

    C. Dima and Salad time limit per test 1 second memory limit per test 256 megabytes input standard in ...

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

    01背包变形,注意dp过程的时候就需要取膜,否则会出错. 代码如下: #include<iostream> #include<cstdio> #include<cstri ...

  7. HDU 4381 Grid

    背包变形. 将操作分为了两类,可以分开处理. 可以dp处理出L[i]:L[i]=-1代表从左到右 i 长度不能被拼凑出来,L[i]!=-1表示从左到右 i 长度能被拼凑出,并且最小费用为L[i]. 反 ...

  8. P1282 多米诺骨牌 (背包变形问题)

    题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S1=6+1+1+1=9, ...

  9. J-流浪西邮之寻找火石碎片 【经典背包变形】

    题目来源:2019 ACM ICPC Xi'an University of Posts & Telecommunications School Contest 链接:https://www. ...

  10. CF#214 C. Dima and Salad 01背包变形

    C. Dima and Salad 题意 有n种水果,第i个水果有一个美味度ai和能量值bi,现在要选择部分水果做沙拉,假如此时选择了m个水果,要保证\(\frac{\sum_{i=1}^ma_i}{ ...

随机推荐

  1. ADB not responding. You can wait more,or kill"abd.exe" process manually and click 'Restart'

    在使用Android Studio进行开发的过程中,有时候编译运行时,会出现如下提示: ADB not responding. You can wait more,or kill"abd.e ...

  2. 【web性能】让css更简洁、高效

    用了这么多年的CSS,现在才明白CSS的真正匹配原理,不知道你是否也跟我一样?   看1个简单的CSS: DIV#divBox p span.red{color:red;},按习惯我们对这个CSS 的 ...

  3. WEB前端介绍

    1.WEB前端是神马 Web前端开发是从网页制作演变而来的,名称上有很明显的时代特征.在互联网的演化进程中,网页制作是Web1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行为也以浏览为 ...

  4. babel安装

    大家都知道目前ES6不是浏览器全部都是支持的,所以要通过转码器先进行转码然后再编译代码.小心在学习ES6之前先安装了babel转码器,虽然当时安装的时候困难重重,遗憾的是没有把解决方案总结一下,别人询 ...

  5. istream, outstream使用及常见错误

    使用方法: 使用filebuf打开文件,并拷贝给istream/ostream. 如下面的例子中,实现读取并处理deseq文件夹下所有文件,输出到ostream fw. code: #include& ...

  6. ajax返回JSON时的处理方式

    JSON中对象通过“{}”来标识,一个“{}”代表一个对象,如{“AreaId”:”123”},对象的值是键值对的形式(key:value). json_encode() 该函数主要用来将数组和对象, ...

  7. 使用 DB Fixtures 为 Unit Test 提供基础数据,Sails + Mocha 实现。

    使用 DB Fixtures 为 Unit Test 提供基础数据,Sails + Mocha 实现. 问题:Test Fixture 太分散,管理麻烦. 在做单元测试的时候,数据回滚是个比较麻烦的问 ...

  8. c++异常 连续抛出异常

      今天天遇到这样一个问题,连续两次抛出异常,但是只有一个catch,会导致core这个时候会导致core, 单线程编程中可能很少遇到这样的问题,但是多线程中是很容易遇到的, 举个例子:catch代码 ...

  9. INDIGO STUDIO神器!快速创建WEB、移动应用的交互原型工具【转】

    转自:http://www.uisdc.com/indigo-studio-wireframe-interactive-uis 这套最新的设计工具出自Indigo工作室,永久免费,有mac版本和WIN ...

  10. python3代码

    import urllib.request url="http://mm.taobao.com/json/request_top_list.htm?type=0&page=1&quo ...