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 ...
随机推荐
- lnmp 安装FTP服务 并配置FTP用户
lnmp 默认是不带FTP服务的,需要的童鞋要自行安装.步骤也很简单 一,进入lnmp目录,找到pureftpd.sh 二,直接运行该脚本 ./pureftpd.sh 按任意键开始安装,等待,安装成功 ...
- HTML+CSS(11)
n CSS背景属性 Background-color:背景色. Background-image:背景图片地址.如:background-image:url(images/bg.gif;) Back ...
- ES6 Template String 模板字符串
模板字符串(Template String)是增强版的字符串,用反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量. 大家可以先看下面一段代码: $(&quo ...
- C#屏蔽Alt+F4,解决Alt+F4关闭窗体时对话框NO后,线程不退出问题
//1.将窗体的属性KeyPrieview设置为true //keypreview属性为true的时候,就可以响应键盘事件v //2.在窗体KeyDown事件中加如下代码 private void F ...
- git解决内容冲突
内容冲突的冲突处理 两个用户修改了同一个文件的同一块区域,git会报告内容冲突. 解决办法:打开发生冲突的文件,会发现 <<<<<<< HEADtest in ...
- X.509 certificate
A digital certificate is a collection of data used to securely distribute the public half of a publi ...
- 微信小程序中的iPhone X适配问题
微信小程序中的iPhone X适配问题 小程序中下方的导航会被iPhone X下面的那条黑线盖住[微笑脸],所以要专门为了iPhone X做样式上的适配[微笑脸] wx.getSystemInfo({ ...
- 模拟登录新浪微博(Python)
PC 登录新浪微博时, 在客户端用js预先对用户名.密码都进行了加密, 而且在POST之前会GET 一组参数,这也将作为POST_DATA 的一部分. 这样, 就不能用通常的那种简单方法来模拟POST ...
- PAT_A1151#LCA in a Binary Tree
Source: PAT A1151 LCA in a Binary Tree (30 分) Description: The lowest common ancestor (LCA) of two n ...
- PAT_A1125#Chain the Ropes
Source: PAT A1125 Chain the Ropes (25 分) Description: Given some segments of rope, you are supposed ...