POJ1837 Balance 背包
题目大意: 有一个天平,天平左右两边各有若干个钩子,总共有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 背包的更多相关文章
- POJ1837 Balance[分组背包]
Balance Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 13717 Accepted: 8616 Descript ...
- 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 ...
- poj 1837 Balance(背包)
题目链接:http://poj.org/problem?id=1837 Balance Time Limit: 1000MS Memory Limit: 30000K Total Submissi ...
- poj1837 Balance
Balance POJ - 1837 题目大意: 有一个天平,天平左右两边各有若干个钩子,总共有C个钩子,有G个钩码,求将钩码全部挂到钩子上使天平平衡的方法的总数. 其中可以把天枰看做一个以x轴0点 ...
- poj1837【背包】
题意: 有一根杆子,给出一些杆子上的位置,位置上能放重物,再给出一些重物的重量. 重物都需要被使用,但是位置不一定都要用到. 问你能有多少种方法让这个杆子平衡. 思路: 在位置上是0/1背包思想,取或 ...
- poj1837 01背包(雾
Description A train has a locomotive that pulls the train with its many passenger coaches. If the lo ...
- POJ1837 Balance(DP)
POJ1837http://poj.org/problem?id=1837 题目大意就是说有一个称上有C个挂钩,告诉你每个挂钩的位置,现在有G个重物,求是之平衡的方法数. 转化一下:DP[i][j]表 ...
- poj 01背包
首先我是按这篇文章来确定题目的. poj3624 Charm Bracelet 模板题 没有要求填满,所以初始化为0就行 #include<cstdio> #include<algo ...
- POJ之01背包系列
poj3624 Charm Bracelet 模板题 没有要求填满,所以初始化为0就行 #include<cstdio> #include<iostream> using na ...
随机推荐
- Oracle 关于oracle自带的行转列函数
前言: 环境是java+hibernate+oracle11g 目标是将某表中根据id分组后将name字段的值拼接到一列中,且用“,“进行分割 试过用 wm_concat() 结合 group by ...
- (转载)实例详解Android快速开发工具类总结
实例详解Android快速开发工具类总结 作者:LiJinlun 字体:[增加 减小] 类型:转载 时间:2016-01-24我要评论 这篇文章主要介绍了实例详解Android快速开发工具类总结的相关 ...
- Android开发圆形ImageView实现
效果图如下 1.自定义属性,在value文件夹下新建attrs文件,声明如下属性 <declare-styleable name="CircleImageView"> ...
- shiro登陆权限验证
一>引入shirojar包 <!-- shiro登陆权限控制 --> <dependency> <groupId>org. ...
- andorid 查看OpenCv Mat的Debug信息
在进行Android调试时,不能再Console显示Debug信息,只能在LogCat上显示,显示信息如下图: 代码段: public void printMat2Txt(Mat ElemM, Str ...
- Mysql分组求和&LIMIT
分组求和mysql> SELECT coalesce(name, '总数'), SUM(singin) as singin_count FROM employee_tbl GROUP BY na ...
- (转)Openlayers 2.X加载高德地图
http://blog.csdn.net/gisshixisheng/article/details/44853881 概述: 前面的有篇文章介绍了Openlayers 2.X下加载天地图,本节介绍O ...
- 迭代器与index遍历
迭代器用于链式组织的序列. index用于线性组织的序列.
- iOS https 证书链获取
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)chall ...
- html 表单赋值 和 时间戳 转换
<script> window.onload = function () { var str; // console.log(@ViewBag.ID); $.post("/Ser ...