一. 题目描述
二. 题目大意
有一个天平有C个挂钩,G个砝码。用上所有的砝码使得这个天平保持平衡。这不就是,初中学过的杠杆原理吗?
2 4 // C,G
-2 3 //挂钩的坐标
3 4 5 8 //每个砝码的重量
三. 解题思路
这是一个01背包类型的动态规划,即每件物品只有一个。设dp[i][j]表示前i个砝码全部挂上去后平衡度为j的挂法有多少种。
平衡度:j=天平右边的力臂-左边的力臂
当挂上前i-1个砝码后,再挂第i个砝码,这时的平衡度只和挂上前i-1个砝码的状态有关,我们假设在天平的某个挂钩挂上第i个砝码后,此时的平衡度为j,那么有dp[i][j]=dp[i-1][j-w[i]*loc[k]],其中loc[k]是某个挂钩的坐标,那么如果每个挂钩都挂这个砝码全都挂一遍,就有dp[i][j]=
∑
1
G
\sum_1^G
∑1Gdp[i-1][j-w[i]*loc[k]]。当然也可以正着想,那么递推方程就是dp[i][j+w[i]*loc[k]]+=dp[i-1][j]
四. AC代码
#include<iostream>
#include<string.h>
using namespace std;
int C, G;
int dp[21][15001];
int loc[21];
int w[21];
int main() {
cin >> C >> G; //C个挂钩,G个砝码
for (int i = 1; i <= C; i++) {
cin >> loc[i];
}
for (int i = 1; i <= G; i++) {
cin >> w[i];
}
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 - w[i] * loc[k]];
}
}
}
cout << dp[G][7500] << endl;
}