Balance
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 15844 | Accepted: 9987 |
Description
Gigel has a strange "balance" and he wants to poise it. Actually, the device is different from any other ordinary balance.
It orders two arms of negligible weight and each arm's length is 15. Some hooks are attached to these arms and Gigel wants to hang up some weights from his collection of G weights (1 <= G <= 20) knowing that these weights have distinct values in the range 1..25. Gigel may droop any weight of any hook but he is forced to use all the weights.
Finally, Gigel managed to balance the device using the experience he gained at the National Olympiad in Informatics. Now he would like to know in how many ways the device can be balanced.
Knowing the repartition of the hooks and the set of the weights write a program that calculates the number of possibilities to balance the device.
It is guaranteed that will exist at least one solution for each test case at the evaluation.
It orders two arms of negligible weight and each arm's length is 15. Some hooks are attached to these arms and Gigel wants to hang up some weights from his collection of G weights (1 <= G <= 20) knowing that these weights have distinct values in the range 1..25. Gigel may droop any weight of any hook but he is forced to use all the weights.
Finally, Gigel managed to balance the device using the experience he gained at the National Olympiad in Informatics. Now he would like to know in how many ways the device can be balanced.
Knowing the repartition of the hooks and the set of the weights write a program that calculates the number of possibilities to balance the device.
It is guaranteed that will exist at least one solution for each test case at the evaluation.
Input
The input has the following structure:
• the first line contains the number C (2 <= C <= 20) and the number G (2 <= G <= 20);
• the next line contains C integer numbers (these numbers are also distinct and sorted in ascending order) in the range -15..15 representing the repartition of the hooks; each number represents the position relative to the center of the balance on the X axis (when no weights are attached the device is balanced and lined up to the X axis; the absolute value of the distances represents the distance between the hook and the balance center and the sign of the numbers determines the arm of the balance to which the hook is attached: '-' for the left arm and '+' for the right arm);
• on the next line there are G natural, distinct and sorted in ascending order numbers in the range 1..25 representing the weights' values.
• the first line contains the number C (2 <= C <= 20) and the number G (2 <= G <= 20);
• the next line contains C integer numbers (these numbers are also distinct and sorted in ascending order) in the range -15..15 representing the repartition of the hooks; each number represents the position relative to the center of the balance on the X axis (when no weights are attached the device is balanced and lined up to the X axis; the absolute value of the distances represents the distance between the hook and the balance center and the sign of the numbers determines the arm of the balance to which the hook is attached: '-' for the left arm and '+' for the right arm);
• on the next line there are G natural, distinct and sorted in ascending order numbers in the range 1..25 representing the weights' values.
Output
The output contains the number M representing the number of possibilities to poise the balance.
Sample Input
2 4 -2 3 3 4 5 8
Sample Output
2
Source
Romania OI 2002
解题思路:
题意是有一个天平 天平的左右有一排钩子 现在往钩子上挂砝码(全挂上)使天平平衡的方案有多少种
输入两个数 第一个数是钩子的数目 第二个数是砝码的数量
第二行 负数代表天平左边的钩子 正数代表右边的钩子 值代表力臂 就是距离天平中心多远
第三行 全是正数 值代表此砝码的重量
本题很明显的动态规划 那么既然是动态规划 我们就依次分析 然后写出动态转移方程
做动态规划的题目 首先一定要弄清楚题目让你求的是什么
求砝码全挂上且天平平衡时的方案数
接下来就是阅读理解 提取关键词
1.砝码全挂上
2.天平平衡
你要进行计算 所以一定要转成数字才行
砝码全挂上----->砝码的数量 (i)
天平平衡-------->左右重量相等 (j)
i现在是最基本的单位 无法分割
但j不是 j=钩子(c[?])*砝码(g[?])
写到现在 那么动态转移方程就很明显了
dp[i][j] += dp[j-1][j-(c[?]*g[?])]
因为钩子负数代表左边 与砝码乘出来的数就是负数 然而数组里不可能有负数
所以我们要消掉负数 怎么消呢? 那就看他最大能负多少 咱给他加回来就变正数了
钩子的位置最左是-15 砝码的重量最大是25 砝码最多有20个
也就是15*25*20 = 7500 正常来讲左右平衡应该是0 现在咱们为了消除负数加上了7500
所以现在平衡的位置变成7500 所以我们最后输出的结果是dp[砝码的数量][7500]
越小于7500 说明左边越沉 越大于7500说明右边越沉
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int m = scanner.nextInt();
int [] c = new int [n];
int [] g = new int [m+1];
for (int i = 0; i < n; i++) {
c[i] = scanner.nextInt();
}
for (int i = 1; i <= m; i++) {
g[i] = scanner.nextInt();
}
int [][] dp = new int [m+1][15001];
dp[0][7500] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 0; j < 15001; j++) {
for (int k = 0; k < n; k++) {
int v = j-c[k]*g[i];
if (v >= 0 && v < 15001) {
dp[i][j] += dp[i-1][v] ;
}
}
}
}
System.out.println(dp[m][7500]);
}
}
}
解题思路:
题意是有一个天平 天平的左右有一排钩子 现在往钩子上挂砝码(全挂上)使天平平衡的方案有多少种
输入两个数 第一个数是钩子的数目 第二个数是砝码的数量
第二行 负数代表天平左边的钩子 正数代表右边的钩子 值代表力臂 就是距离天平中心多远
第三行 全是正数 值代表此砝码的重量
本题很明显的动态规划 那么既然是动态规划 我们就依次分析 然后写出动态转移方程
做动态规划的题目 首先一定要弄清楚题目让你求的是什么
求砝码全挂上且天平平衡时的方案数
接下来就是阅读理解 提取关键词
1.砝码全挂上
2.天平平衡
你要进行计算 所以一定要转成数字才行
砝码全挂上----->砝码的数量 (i)
天平平衡-------->左右重量相等 (j)
i现在是最基本的单位 无法分割
但j不是 j=钩子(c[?])*砝码(g[?])
写到现在 那么动态转移方程就很明显了
dp[i][j] += dp[j-1][j-(c[?]*g[?])]
因为钩子负数代表左边 与砝码乘出来的数就是负数 然而数组里不可能有负数
所以我们要消掉负数 怎么消呢? 那就看他最大能负多少 咱给他加回来就变正数了
钩子的位置最左是-15 砝码的重量最大是25 砝码最多有20个
也就是15*25*20 = 7500 正常来讲左右平衡应该是0 现在咱们为了消除负数加上了7500
所以现在平衡的位置变成7500 所以我们最后输出的结果是dp[砝码的数量][7500]
越小于7500 说明左边越沉 越大于7500说明右边越沉
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int m = scanner.nextInt();
int [] c = new int [n];
int [] g = new int [m+1];
for (int i = 0; i < n; i++) {
c[i] = scanner.nextInt();
}
for (int i = 1; i <= m; i++) {
g[i] = scanner.nextInt();
}
int [][] dp = new int [m+1][15001];
dp[0][7500] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 0; j < 15001; j++) {
for (int k = 0; k < n; k++) {
int v = j-c[k]*g[i];
if (v >= 0 && v < 15001) {
dp[i][j] += dp[i-1][v] ;
}
}
}
}
System.out.println(dp[m][7500]);
}
}
}