题目翻译
吉格尔有一种奇怪的“平衡”,他想保持平衡。实际上,该装置不同于任何其他普通天平。
它让两条重量可以忽略不计的手臂,每条手臂的长度为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;
}