题目大意: 有一个天平,天平左右两边各有若干个钩子,总共有C个钩子(每个钩子有相对于中心的距离,左负右正),有G个钩码,求将钩码全部挂到钩子上使天平平衡的方法的总数。

将每个砝码看作一组,组内各个物品的体积为每个挂钩与该砝码形成的力矩,背包总体积严格为0,这便是分组背包计数问题(特殊点:每一组必须出一个物品,而不是至多出一个物品)。由于c++不允许负的数组下标,所以每次更新时,j要加上offsetJ。

实现分组背包计数问题时,可以用填表法(找以前节点求自己值)(DP1)或刷表法(找以后节点更新以后值)(DP2)。由于刷表法时,如果DP[i][j]==0,可以跳过,所以节省时间。

注意:

  • 不可以用一维数组倒序循环来表示DP数组,因为j-objV可能比j还大
  • 同理,每次判断时,不是j-objV>=0,0代表天平的支点而不是左端点。所以应当为j-objV>=minJ。
#include <cstdio>
#include <cstring>
#include <cstdarg>
using namespace std; const int MAX_V = , MAX_OBJ = , MAX_HOOP = ;
const int Plus = ;
#define Sub(x) x+offsetJ
int TotHoop;
int Len[MAX_HOOP], W[MAX_OBJ]; void _printf(char *format, ...)
{
#ifdef _DEBUG
va_list(args);
va_start(args, format);
vprintf(format, args);
va_end(args);
#endif
} int DP1(int totHoop, int totDev, int *_w, int *_len)
{
int minJ = , maxJ = , wSum = , offsetJ, objV = ;
static int DP[MAX_OBJ][MAX_V];
for (int dev = ; dev <= totDev; dev++)
wSum += _w[dev];
for (int hoop = ; hoop <= totHoop; hoop++)
_len[hoop] > ? maxJ += _len[hoop] * wSum : minJ += _len[hoop] * wSum;
offsetJ = -minJ;
DP[][offsetJ] = ;
_printf("+ offsetJ %d maxJ %d\n", +offsetJ, maxJ);
for (int i = ; i <= totDev; i++)
for (int j = minJ; j <= maxJ; j++)
for (int hoop = ; hoop <= totHoop; hoop++)
{
objV = _w[i] * _len[hoop];
if (j - objV >= minJ && j - objV <= maxJ)
{
DP[i][j + offsetJ] += DP[(i - )][j + offsetJ - objV];
_printf("%d=DP[%d][%d] += DP[%d][%d]=%d\n", DP[i][j + offsetJ], i, j, i - , j - _w[i] * _len[hoop], DP[i - ][j - _w[i] * _len[hoop] + offsetJ]);
}
}
return DP[totDev][offsetJ];
} int DP2(int totHoop, int totDev, int *_w, int *_len)
{
int minJ = , maxJ = , wSum = , offsetJ, objV = ;
static int DP[MAX_OBJ][MAX_V];
for (int dev = ; dev <= totDev; dev++)
wSum += _w[dev];
for (int hoop = ; hoop <= totHoop; hoop++)
_len[hoop] > ? maxJ += _len[hoop] * wSum : minJ += _len[hoop] * wSum;
offsetJ = -minJ;
DP[][offsetJ] = ;
_printf("+ offsetJ %d maxJ %d\n", + offsetJ, maxJ);
for (int i = ; i < totDev; i++)
for (int j = minJ; j <= maxJ; j++)
if (DP[i][j+ offsetJ])
for (int hoop = ; hoop <= totHoop; hoop++)
{
objV = _w[i+] * _len[hoop];
DP[i + ][j + objV + offsetJ] += DP[i][j + offsetJ];
_printf("%d=DP[%d][%d] += DP[%d][%d]=%d\n", DP[i+][j+objV+ offsetJ], i+, j+objV+ offsetJ, i, j+ offsetJ , DP[i][j + offsetJ]);
}
return DP[totDev][offsetJ];
} int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
int totDevice, vCnt = , totV = , maxV = , minV = ;
scanf("%d%d", &TotHoop, &totDevice);
for (int i = ; i <= TotHoop; i++)
scanf("%d", i + Len);
for (int i = ; i <= totDevice; i++)
scanf("%d", i + W);
printf("%d\n", DP2(TotHoop, totDevice, W, Len));
return ;
}

POJ1837 Balance 背包的更多相关文章

  1. POJ1837 Balance[分组背包]

    Balance Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13717   Accepted: 8616 Descript ...

  2. HDU 5616 Jam's balance 背包DP

    Jam's balance Problem Description Jim has a balance and N weights. (1≤N≤20)The balance can only tell ...

  3. poj 1837 Balance(背包)

    题目链接:http://poj.org/problem?id=1837 Balance Time Limit: 1000MS   Memory Limit: 30000K Total Submissi ...

  4. poj1837 Balance

    Balance  POJ - 1837 题目大意: 有一个天平,天平左右两边各有若干个钩子,总共有C个钩子,有G个钩码,求将钩码全部挂到钩子上使天平平衡的方法的总数. 其中可以把天枰看做一个以x轴0点 ...

  5. poj1837【背包】

    题意: 有一根杆子,给出一些杆子上的位置,位置上能放重物,再给出一些重物的重量. 重物都需要被使用,但是位置不一定都要用到. 问你能有多少种方法让这个杆子平衡. 思路: 在位置上是0/1背包思想,取或 ...

  6. poj1837 01背包(雾

    Description A train has a locomotive that pulls the train with its many passenger coaches. If the lo ...

  7. POJ1837 Balance(DP)

    POJ1837http://poj.org/problem?id=1837 题目大意就是说有一个称上有C个挂钩,告诉你每个挂钩的位置,现在有G个重物,求是之平衡的方法数. 转化一下:DP[i][j]表 ...

  8. poj 01背包

    首先我是按这篇文章来确定题目的. poj3624 Charm Bracelet 模板题 没有要求填满,所以初始化为0就行 #include<cstdio> #include<algo ...

  9. POJ之01背包系列

    poj3624 Charm Bracelet 模板题 没有要求填满,所以初始化为0就行 #include<cstdio> #include<iostream> using na ...

随机推荐

  1. Spark Streaming概述

    Spark Streaming是一种构建在Spark上的实时计算框架,它扩展了Spark处理大规模流式数据的能力. 其中包括:资源管理框架,Apache YARN.Apache Mesos:基于内存的 ...

  2. html中canvas渲染图片,并转化成base64格式保存

    最近在做一个上传头像然后保存显示的功能,因为涉及到裁剪大小和尺寸比例,所以直接上传图片再展示的话,就会出现问题,所以就想用canvas来渲染裁剪后的图片,然后转化成base64格式的图片再存储,这样取 ...

  3. CSS样式优先级和权重问题(部分)

    内联样式: <div style="font-size: 12px;">姓名</div> 外部样式: <link rel="styleshe ...

  4. 通过Web Service实现IP地址查询功能

    实例01 实现一个简单的Web服务访问 本实例将实现IP地址查询接口服务,根据用户传入的IP地址返回IP所在的省.市.地区,实例中将会用到IP地址库用于查询信息,由于数据较多,所以读者可在光盘资源文件 ...

  5. 利用VMware14安装虚拟机(Win7&CentOS6.4)

    安装Win7 https://blog.csdn.net/Yangchenju/article/details/80694597 安装CentOS6.4 https://blog.csdn.net/u ...

  6. YTBro Video 2016-07-30 Sat

    明日天气:多云转阴,32~24度 运动向 健身 20中极致疯狂的俯卧撑,新手请勿尝试 跑酷 大神放大招,招招见血,不信你看 赛事 2016年世界室内田径锦标赛 男子4×400接力决赛 台球 RP集中爆 ...

  7. 【sqli-labs】 less13 POST - Double Injection - Single quotes- String -twist (POST型单引号变形双注入)

    报错 闭合掉括号 这关登录成功之后不显示登录的用户名密码了

  8. Day 20 re模块(正则表达式)

    re模块 作用:取文本或者字符串内找你所需要的东西 import re re.findall(参数一,参数二,参数三) #暂时用到前两个,第一个为正则表达式,第二个为字符串,也就是被搜索的文本 ^元字 ...

  9. mac上如何设置ssh不断掉,并且session保持

    ➜ ~ pwd /Users/muahao ➜ ~ cat ~/.ssh/config Host * ServerAliveInterval 60 ControlMaster auto Control ...

  10. leetcode 188-maxProfit

    public static int maxProfit(int k, int[] prices) { if (0 >= k || null == prices || 1 >= prices ...