题意:

给定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. JavaWeb项目开发案例精粹-第4章博客网站系统-001设计

    1. 2. 3. # MySQL-Front 5.0 (Build 1.0) /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE */; /*!40101 SET SQL_MO ...

  2. FreePascal经典资料

    ------------------------------------------------------------------------ 这是每个版本的changelog: http://bu ...

  3. SSM整合配置

    SSM三大框架整合详细教程(Spring+SpringMVC+MyBatis) 使用SSM(Spring.SpringMVC和Mybatis)已经有三个多月了,项目在技术上已经没有什么难点了,基于现有 ...

  4. FastDFS之java客户端使用

    为了方便应用程序的访问FastDFS,官网提供了fastdfs-client-java,以便更好的与应用程序结合使用. 下载fastdfs-client-java源码添加到项目工程里面,添加配置文件: ...

  5. 280. Wiggle Sort

    题目: Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] ...

  6. Linux系统文件权限&目录权限

    linux系统一切都是文件,文件和目录的所属与权限--来分别规定所有者.所有组.其余人的读.写.执行权限. 读(read),写(write),执行(excute)简写为(r.w.x),也可以以用(4. ...

  7. AdventureWorksDW2008R2 attach: Unable to open the physical file. Operating system error 5: "5(Access is denied.)

    http://stackoverflow.com/questions/26014133/adventureworksdw2008r2-attach-unable-to-open-the-physica ...

  8. Java 数据结构之Stack

    Stack类表示后进先出(LIFO)的对象堆栈.栈是一种非常常见的数据结构.Stack继承Vector,并对其进行了扩展. 用法: 1.只有一个构造函数: public Stack() {} 2.创建 ...

  9. 用Spring Data JPA 基于内存存储pojo的简单案例

    poject结构如下: Customer.java类是一个pojo类,代码如下: package hello; import javax.persistence.Entity; import java ...

  10. linux查看某个端口被占用

    如8003 端口 使用命令:netstat -nlptu |awk '{print $4,$7}' | grep 8003 [root[@bogon](/user/bogon) ~]# netstat ...