题目链接:https://vjudge.net/contest/103424#problem/I

转载于:>>>大牛博客

题目大意:

有 n 个货物,并且知道了每个货物的重量,每次用载重量分别为c1,c2的火车装载,问最少需要运送多少次可以将货物运完。

解题分析:

物品个数最多是10个,可以用0和1分别表示物品是否被选中运送

假设有3个物品,那么可以用001表示当前这一次选择将第3个物品运走

那么,所有的状态可以用0~2^n-1对应的二进制数表示出来

对于上述每一种状态,选择其中可以一次运走的状态进行01背包

其中,所有位全部为1的二进制数表示背包总体积

每个物品的体积是该状态对应二进制数中1的个数

为了把物品全部运走,要选择一些状态把背包的1全部被填满

值得注意的是,因为一件物品不会被运2次,所以所有选取的状态应该是没有交集的

比如1001101和1110010是不行的,第一件物品被运了2次

然后为了使次数最小,可以将次数抽象成01背包中的物品价值,每种状态对应运送一次,价值是1

 

如何判断某种状态是否可以一次运走?

因为有2辆车,所以将要判断该状态是否能分成满足体积分别小于等于车体积的2份,

如何从十进制中取出该状态被选择的物体?

也就是将二进制中的1的位置取出来

利用 :>> :右移运算符 << 左移运算符  & 按位与运算符

假设有一个二进制数: x  =  01101

那么将它右移2位  : x>>=2,他会变成 00011(移出位被丢弃,左边移出的空位或者一律补0,或者补符号位)

我们知道1的二进制数是最后一位为1其他全为0,如果某数的二进制从又往左数第2位是1,移位之后这个1

变成最后一位,和二进制只有最后一位是1的数字1&之后还是1,而如果某数的二进制从又往左数第2位是0

的话,和二进制只有最后一位是1的数字1&之后将是0(因为1除了最后一位其他位全为0,而该数移位后最后一位是0)

综上所述      (x>>i)&1可以判断x从右往左第i位是0还是1【同理(x&(1<<i))也可以判断】

知道怎么找到二进制数中1的位置基本状压的代码也不难懂了

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#define mem(a,x) memset(a,x,sizeof(a))
#define inf 1<<30
using namespace std;
const double PI = acos(-1.0);
typedef long long LL;
int state[];
int dp[];
bool vis[];
int n,v1,v2,tot;
int c[];
bool ok(int x)//判断一种状态是否可行(可以一次运走)
{
int sun = ;
mem(vis,);
vis[] = ;
for (int i = ;i < n;i++)
{
if ((x>>i)&)
{
sun += c[i];
for (int j = v1;j >= c[i];j--) //这个真的非常巧妙 开始看半天都不懂,自己模拟一遍才懂
{ //比如说此状态有c1、c2、c3,3个体积,第一次操作把体积c1标记为1,
if (vis[j-c[i]]) //第二次操作把c2和c1+c2两种体积标记为1,第三次把c3和前面的组合标记为1,
vis[j] = ; //最后这些体积能组合成的所有体积就都被标记成了1
}
}
}
if (sun > v1+v2)//装不下
return ;
//总体积小不代表一定装得下,拆分成2份要2份都装得下
for (int i = ;i <= v1;i++)
{
if (vis[i]&&sun-i <= v2)//如果存在(i,sun-i)这样的组合
return ; //满足i可以被v1装下(前面for循环是对于v1的,vis[i]表示体积i可以被v1装下),sun-i可以被v2装下
}
return ;
}
void init()//初始化找到满足条件的状态
{
tot = ;
for (int i = ;i < (<<n);i++)
{
dp[i] = inf;
if (ok(i))
state[tot++] = i;
}
}
int main()
{
int T;
cin>>T;
int oo = ;
while (T--)
{
cin>>n>>v1>>v2;
for (int i = ;i < n;i++)
scanf("%d",&c[i]);
init();
int V = (<<n) - ;//V是n个1的二进制数
dp[] = ;//没有物品当然是0次运走
for (int i = ;i < tot;i++)
{
for (int j = V;j >= ;j--)
{
if (dp[j] == inf)
continue; //原版的背包是dp[j] = min(dp[j],dp[j-c[i]]+w[i])
//但是显然二进制不好表示减,但是可以用|抽象加
//这就相当于背包改版成dp[j+c[i]] = min(dp[j+c[i]],dp[j] + w[i])
if ((j&state[i])==) //当然2种状态不能有交集
{
dp[j|state[i]] = min(dp[j|state[i]] ,dp[j] + );
} }
}
printf("Scenario #%d:\n%d\n",++oo,dp[V]);
if (T) puts("");
}
return ;
}

2018-05-13

POJ 2923 Relocation 装车问题 【状态压缩DP】+【01背包】的更多相关文章

  1. POJ 1691 Painting a Board(状态压缩DP)

    Description The CE digital company has built an Automatic Painting Machine (APM) to paint a flat boa ...

  2. poj 3311 floyd+dfs或状态压缩dp 两种方法

    Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6436   Accepted: 3470 ...

  3. POJ 2686_Traveling by Stagecoach【状态压缩DP】

    题意: 一共有m个城市,城市之间有双向路连接,一个人有n张马车票,一张马车票只能走一条路,走一条路的时间为这条路的长度除以使用的马车票上规定的马车数,问这个人从a出发到b最少使用时间. 分析: 状态压 ...

  4. HDU 6125 Free from square 状态压缩DP + 分组背包

    Free from square Problem Description There is a set including all positive integers that are not mor ...

  5. POJ 2923 Relocation (状态压缩,01背包)

    题意:有n个(n<=10)物品,两辆车,装载量为c1和c2,每次两辆车可以运一些物品,一起走.但每辆车物品的总重量不能超过该车的容量.问最少要几次运完. 思路:由于n较小,可以用状态压缩来求解. ...

  6. poj 2411 Mondriaan's Dream_状态压缩dp

    题意:给我们1*2的骨牌,问我们一个n*m的棋盘有多少种放满的方案. 思路: 状态压缩不懂看,http://blog.csdn.net/neng18/article/details/18425765 ...

  7. poj 1185 炮兵阵地 [经典状态压缩DP]

    题意:略. 思路:由于每个大炮射程为2,所以如果对每一行状态压缩的话,能对它造成影响的就是上面的两行. 这里用dp[row][state1][state2]表示第row行状态为state2,第row- ...

  8. POJ 1038 Bug Integrated Inc(状态压缩DP)

    Description Bugs Integrated, Inc. is a major manufacturer of advanced memory chips. They are launchi ...

  9. poj 2411 Mondriaan's Dream(状态压缩dP)

    题目:http://poj.org/problem?id=2411 Input The input contains several test cases. Each test case is mad ...

随机推荐

  1. css命名规范: BEM 的命名法

    整理自:前端早读课[第1183期]这些 CSS 命名规范,将省下你大把调试时间 试图解决 3 类问题: 仅从名字就能知道一个 CSS 选择器具体做什么 从名字能大致清楚一个选择器可以在哪里使用 从 C ...

  2. TypeError: view must be a callable or a list/tuple in the case of include()

    原文连接: http://www.imooc.com/qadetail/98920 我是这么写的就好了 from django.conf.urls import url from django.con ...

  3. JS window对象的top、parent、opener含义介绍

    1.top该变更永远指分割窗口最高层次的浏览器窗口.如果计划从分割窗口的最高层次开始执行命令,就可以用top变量. 2.openeropener用于在window.open的页面引用执行该window ...

  4. Linux input子系统简介

    1.前言 本文主要对Linux下的input子系统进行介绍 2. 软件架构 图 input子系统结构图 input子系统主要包括三个部分:设备驱动层.核心层和事件层.我们可以分别理解为:具体的输入设备 ...

  5. GCC制作动态库导出符号表【转】

    转自:https://blog.csdn.net/whb_fei/article/details/76974543 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...

  6. 一个有趣的小例子,带你入门协程模块-asyncio

    一个有趣的小例子,带你入门协程模块-asyncio 上篇文章写了关于yield from的用法,简单的了解异步模式,[https://www.cnblogs.com/c-x-a/p/10106031. ...

  7. javascript中cookie常用操作

    //写cookies function setCookie(c_name, value, expiredays){ var exdate=new Date(); exdate.setTime(exda ...

  8. Python3学习笔记11-循环语句

    条件判断使用if,需要加上冒号,当条件判断为True时,执行if下的代码块,为false就什么也不做 只要var1不是0,非空字符串,非空list等,就判断为True.否则为False var1 = ...

  9. SVN设置必须锁定

    SVN是一个开放源代码的版本控制系统,相信做开发的基本上都用过,这里就不多介绍了.团队协作开发时常常会出现提交的文档互相冲突的问题,这里给大家介绍一下给SVN文件设置必须锁定的方法,当然你也可以对冲突 ...

  10. 修改centos和ubuntu ssh远程连接端口提升系统安全性

    #修改centos服务器ssh端口 sed -i 's/#Port 22/Port 38390/' /etc/ssh/sshd_config sed -i 's/^GSSAPIAuthenticati ...