poj-1837-dp-java

本文介绍了一个关于平衡天平的问题,通过使用动态规划的方法来找出所有可能的平衡方案。具体包括输入数据的解析、状态转移方程的设计及核心代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

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.

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]);
         }
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值