Q: 如何判断几件物品能否被 2 辆车一次拉走?

A: DP 问题. 先 dp 求解第一辆车能够装下的最大的重量, 然后计算剩下的重量之和是否小于第二辆车的 capacity, 若小于, 这 OK.

Description

Emma and Eric are moving to their new house they bought after returning from their honeymoon. Fortunately, they have a few friends helping them relocate. To move the furniture, they only have two compact cars, which complicates everything a bit. Since the furniture does not fit into the cars, Eric wants to put them on top of the cars. However, both cars only support a certain weight on their roof, so they will have to do several trips to transport everything. The schedule for the move is planed like this:

  1. At their old place, they will put furniture on both cars.
  2. Then, they will drive to their new place with the two cars and carry the furniture upstairs.
  3. Finally, everybody will return to their old place and the process continues until everything is moved to the new place.

Note, that the group is always staying together so that they can have more fun and nobody feels lonely. Since the distance between the houses is quite large, Eric wants to make as few trips as possible.

Given the weights wi of each individual piece of furniture and the capacities C1 and C2 of the two cars, how many trips to the new house does the party have to make to move all the furniture? If a car has capacity C, the sum of the weights of all the furniture it loads for one trip can be at most C.

Input

The first line contains the number of scenarios. Each scenario consists of one line containing three numbers nC1 and C2C1 and C2 are the capacities of the cars (1 ≤ Ci ≤ 100) and n is the number of pieces of furniture (1 ≤ n ≤ 10). The following line will contain n integers w1, …, wn, the weights of the furniture (1 ≤ wi ≤ 100). It is guaranteed that each piece of furniture can be loaded by at least one of the two cars.

Output

The output for every scenario begins with a line containing “Scenario #i:”, where i is the number of the scenario starting at 1. Then print a single line with the number of trips to the new house they have to make to move all the furniture. Terminate each scenario with a blank line.

Sample Input

2
6 12 13
3 9 13 3 10 11
7 1 100
1 2 33 50 50 67 98

Sample Output

Scenario #1:
2 Scenario #2:
3

思路:

  1. 题目给出, 一共 10 件家具, 所以可以使用状态压缩描述家具被装走的情况
  2. 检查所有的状态(共 1<<n), 并判断其能够被 2 辆车一次带走, 可以的状态存储到 state 数组
  3. 对 state 数组进行01 背包, 状态转移方程为 dp[s|state] = min(dp[s|state], dp[state]+1), 显然是个 push 的过程

总结:

  1. 状态比较少时, 应该形成考虑状态压缩的思维定式, 就像 n<15 时可以暴力破解一样
  2. 状态转移方程有 push 和 pull 两种, push 是指根据当前状态s来更新另一个状态 news; pull 是指通过另一个状态来更新当前状态
  3. 在思路(3)的状态转移方程中可以看出, 当前状态是 state, 另一个状态是 s|state, 所以是 push
  4. 处理状态压缩问题时, 读入的数组从 0 开始比较好, 因为 1<<I, I 总是从0 开始的
  5. 代码第 48 行, 没判断 j &(state[i]) 导致 TLE 一次

代码:

#include <iostream>
using namespace std; const int INF = 0X3F3F3F3F;
const int MAXN = 10 + 1<<11;
int N, C1, C2;
int a[15];
bool dp[MAXN];
int dp2[MAXN];
int state[MAXN]; bool check(const int &s) {
memset(dp, 0, sizeof(dp));
dp[0] = true;
int sum = 0;
for(int i = 0; i < N; i ++) {
if(s & (1<<i)) { // 第 i 位为 1
sum += a[i];
for(int j = C1; j >= a[i]; j--) { // 背包的容量是 C1, 01背包逆序遍历
if(dp[j-a[i]])
dp[j] = true;
}
}
}
for(int i = 0; i <= sum; i++) { // 本来写成 C1
if(dp[i] && sum-i <= C2) {
return true;
}
}
return false;
} int solve_dp() {
memset(state, 0, sizeof(state));
int len = 0;
int inf = 1<<N;
for(int i = 0; i <= inf; i ++) { // <=
if(check(i))
state[len++] = i;
} // 第二次背包
memset(dp2, 0x3f, sizeof(dp2)); // 初始化为 INF
dp2[0] = 0;
for(int i = 0; i < len; i ++) {
for(int j = inf; j >= 0; j --) {
if(!(j & (state[i]))) {
dp2[j|state[i]] = min(dp2[j|state[i]], dp2[j]+1);
}
}
}
return dp2[(1<<N)-1];
}
int main() {
freopen("E:\\Copy\\ACM\\测试用例\\in.txt", "r", stdin);
int testcase;
cin >> testcase;
int tc = 0;
while(testcase--) {
tc++;
scanf("%d%d%d", &N, &C1, &C2);
for(int i = 0; i < N; i ++) {
scanf("%d", &a[i]);
}
// solve
printf("Scenario #%d:\n%d\n\n", tc, solve_dp());
}
return 0;
}

  

update 2014年3月14日15:30:07

1. 总结 (5), 为什么不添加判断会超时? 假如不添加判断, 那么当 j&state[i] != 0 时也会执行状态转移方程. 考虑状态 state[k] 是 state[i] 的子集, 同时 j&state[k] == 0, 那么

j|state[i] == j|state[j] 同时 dp[j|state[i]] >= dp[j|state[k]], 所以对 j&state[i] != 0 的 case, 直接 continue 就好

POJ 2923 Relocation(01背包变形, 状态压缩DP)的更多相关文章

  1. POJ 2923 Relocation 装车问题 【状态压缩DP】+【01背包】

    题目链接:https://vjudge.net/contest/103424#problem/I 转载于:>>>大牛博客 题目大意: 有 n 个货物,并且知道了每个货物的重量,每次用 ...

  2. POJ 2923 【01背包+状态压缩/状压DP】

    题目链接 Emma and Eric are moving to their new house they bought after returning from their honeymoon. F ...

  3. poj 2441 Arrange the Bulls(状态压缩dp)

    Description Farmer Johnson's Bulls love playing basketball very much. But none of them would like to ...

  4. POJ 1185 炮兵阵地 经典的 状态压缩dp

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16619   Accepted: 6325 Description ...

  5. poj 2411 Mondriaan's Dream(状态压缩dp)

    Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, af ...

  6. POJ 2411 Mondriaan's Dream [经典状态压缩dp]

    题意:略. 思路:这一题开始做的时候完全没有思路,便去看了别人的题解. 首先,对于这个题目解法想有一个初步的了解,请看这里:http://www.2cto.com/kf/201208/146894.h ...

  7. POJ 1837 Balance(01背包变形, 枚举DP)

    Q: dp 数组应该怎么设置? A: dp[i][j] 表示前 i 件物品放入天平后形成平衡度为 j 的方案数 题意: 有一个天平, 天平的两侧可以挂上重物, 给定 C 个钩子和G个秤砣. 2 4 - ...

  8. POJ 2441 Arrange the Bulls(状态压缩DP)

    题意很简单,n头牛,m个位置,每头牛有各自喜欢的位置,问安排这n头牛使得每头牛都在各自喜欢的位置有几种安排方法. 2000MS代码: #include <cstdio> #include ...

  9. POJ 2836:Rectangular Covering(状态压缩DP)

    题目大意:在一个平面内有若干个点,要求用一些矩形覆盖它们,一个矩形至少覆盖两个点,可以相互重叠,求矩形最小总面积. 分析: 数据很小,很容易想到状压DP,我们把点是否被覆盖用0,1表示然后放在一起得到 ...

随机推荐

  1. Spring Boot干货系列:(八)数据存储篇-SQL关系型数据库之JdbcTemplate的使用

    Spring Boot干货系列:(八)数据存储篇-SQL关系型数据库之JdbcTemplate的使用 原创 2017-04-13 嘟嘟MD 嘟爷java超神学堂 前言 前面几章介绍了一些基础,但都是静 ...

  2. 也谈免拆机破解中兴B860av1.1(解决不能安装软件/解决遥控)

    20170221更新   部分用户(自己恢复出厂测试过),操作后仍然无法直接在当贝市场安装应用了,    在第8条,最后两步,先改为中国通用市场,后面再改为未知局方.    如果开机想优先启动当贝桌面 ...

  3. linux oracle 查看版本

    1.查找 which sqlplus /u01/app/oracle/product/10.2.0/db_1/bin/sqlplus 可以带出 oracle 安装地址  2.登录 sqlplus 输入 ...

  4. 接收与发送邮件(XE10.2+WIN764)

    千万不要用QQ邮箱测试,我试了半天,没整明白. 一.设置信息 POP3接收邮件POP3服务器:exchange.grandsoft.com.cn端口:110账号:zhujq-a@glodon.com密 ...

  5. css3和jquery实现的可折叠导航菜单(适合手机网页)

    之前为大家介绍了好几款css3导航,今天为大家在介绍的是一款适合放在手机网页的导航菜单.点击列表图标以下拉式的形式显示菜单,单击关闭,动画关闭.效果相当不错.效果图如下: 在线预览   源码下载 这个 ...

  6. HTML5 Canvas 梦幻的文字飞扬动画教程

    之前为大家介绍了一款HTML5/CSS3 3D文字特效 文字外翻效果.今天为大家带来的是html5 canvas实现的文字漂动动画效果.画面非常梦幻. 在线预览   源码下载 实现代码如下: html ...

  7. 迭代获取ViewState

    string s=""; System.Collections.IDictionaryEnumerator ie=ViewState.GetEnumerator(); while ...

  8. 3DS更新R4烧录卡内核

    机子是N3DSLL,用的R4烧录卡是银卡HK版. 关于R4烧录卡的基础知识科普贴: https://tieba.baidu.com/p/4855297365 为了防止该网页挂掉还是存图吧. 找最新内核 ...

  9. mysql客户端(Navicat)远程登录操作遇到问题1142 - XXX command denied to ×××

    新建的dbtest用户,访问新建立的TestDB数据库每次都提示1142错误(已经对数据库TestDB赋予了所有权限) 解决方法: Mysql命令: GRANT SELECT ON mysql.* T ...

  10. CI循环数组问题

    当我们在Controll中把数据传递到view中如: $data['cates_data']=$this->Category_Model->byid_data($id); #调用模型层查询 ...