每天一道英文题,ICPC不自闭(15)

POJ 1837

题目翻译

吉格尔有一种奇怪的“平衡”,他想保持平衡。实际上,该装置不同于任何其他普通天平。

它让两条重量可以忽略不计的手臂,每条手臂的长度为15。一些钩子连接到这些臂上,Gigel想挂起他收集的G重量(1<=G<=20)中的一些重量,因为知道这些重量在1--25范围内有不同的值。Gigel可以放下任何钩子的任何重量,但他必须使用所有重量。

最后,Gigel利用在全国信息学奥林匹克运动会上获得的经验,成功地平衡了设备。现在,他想知道该设备可以通过多少种方式实现平衡。

保证评测时每个测试用例至少存在一个解决方案。

输入

输入具有以下结构:

  • 第一行包含数字 C(2<=C<=20)和数字 G(2<=G<=20);
  • 下一行包含-15~15范围内的 C整数(这些数字也是不同的,并按升序排序)代表吊钩的重新分配;每个数字表示相对于 X轴 上天平中心的位置(当未连接砝码时,装置平衡并与 X轴对齐;距离的绝对值表示吊钩和平衡中心之间的距离,数字的符号确定吊钩连接到的平衡臂:“-”表示左臂,“+”表示右臂)
  • 在下一行中,有 G 个自然、不同且按升序排列的数字,范围为 1--25 表示权重值。

输出

输出包含表示平衡平衡可能性数量的数字 M。

样例

输入

2 4	
-2 3 
3 4 5 8

输出

2

解题思路

首先我们可以知道,当天平平衡时,天平左右的力矩相等,力矩=力臂*力。

相信我们看数据量和题目要求可以多多少少想到动态规划(不想这个我也确实没啥别的方法了)

创建一个二维数组 dp[i][j]。代表放上前 i 个砝码后,天平左力矩与右力矩相差为 j(可能为负值)的方案数量

由于这里的 j 是一个相对量,我们可假设所有物品都放在一边,那么相差量可能为最大也可能最小(此时负值),当最大/最小时绝对值为20*15*25=7500,所以为了避免数组中出现负值,于是我们可以假设相差量为 0 时 j=7500,即将整体加个7500的偏移量,小于7500时,j为负,大于7500时 j 为正。

我们得到方程 dp[i][j+c[k]*g[i]]=dp[i][j+c[k]*g[i]]+dp[i-1][j],k为枚举变量。

代码示例

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;

int C,G;
int dp[50][10010];
int pos[10010];
int wei[10010];

int main(){
	cin>>C>>G;
	for(int i=1;i<=C;i++) cin>>pos[i];
	for(int i=1;i<=G;i++) cin>>wei[i];
	memset(dp,0,sizeof(dp));
	dp[0][7500]=1;
	for(int i=1;i<=G;i++){
		for(int j=0;j<=15000;j++){
			for(int k=1;k<=C;k++){
				dp[i][j]+=dp[i-1][j-wei[i]*pos[k]];
			}
		}
	}
	cout<<dp[G][7500]<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值