• POJ 1837.Balance


    Balance
    Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u

    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

     

     
     
    动态规划问题
     


    状态分析

    采用动态规划,可以看出有一维是使用前i个砝码
    最后一层的意义是:将第i个砝码加入到天平系统中,使天平达到平衡
    则每一层的意义是:将第i个砝码加入到天平系统中,使天平达到特定的状态
    对于天平来说,平衡状态可以用力矩表示

    i为使用的砝码个数 j为力矩
    答案应该为dp[G][0],即使用G个砝码(全部用完),并且力矩为0(保持平衡)

    初始状态为dp[0][0]=1(使用前0个砝码时保持平衡,即不放置砝码平衡)

    按照样例有:

    dp[4][0]=dp[3][16]+dp[3][-24]
      dp[3][16]=dp[2][26]+dp[2][1]
        dp[2][26]=dp[1][34]+dp[1][13]
          dp[1][13]=dp[0][19]+dp[0][4]
          dp[1][34]=dp[0][40]+dp[0][25]
        dp[2][1]=dp[1][9]+dp[1][-11]
          dp[1][9]=dp[0][15]+dp[0][0]
          dp[1][-11]=dp[0][-5]+dp[0][-20]
      dp[3][-24]=dp[2][-14]+dp[2][-39]
        dp[2][-14]=dp[1][-6]+dp[1][-28]
          dp[1][-6]=dp[0][0]+dp[0][-15]
          dp[1][-28]=dp[0][-22]+dp[0][-37]
        dp[2][-39]=dp[1][-31]+dp[1][-51]
          dp[1][-31]=dp[0][-25]+dp[0][-40]
          dp[1][-51]=dp[0][-45]+dp[0][-60]

    dp[i][j]=dp[i-1][j-weight[i]*hook[0]]+dp[i-1][j-weight[i]*hook[1]]+......
    即 使用i个砝码且力矩为j 等于 使用i-1个砝码且力矩为(j减去砝码i可能的力矩)

    也即dp[i][j]+=dp[i-1][j-weight[i]*hook[k]]    k=0,1......k-1

    由于下标不能为负数,因此要将力矩变为正数
    钩子在-15~+15之间 砝码最多20个,每个最终25 即力矩最大为 15*20*25=7500

    原力矩范围为 -7500~0~7500
    加上7500后有 0~7500~15000

    AC的代码:Github

      1 /*
      2 By:OhYee
      3 Github:OhYee
      4 Email:oyohyee@oyohyee.com
      5 Blog:http://www.cnblogs.com/ohyee/
      6 
      7 かしこいかわいい?
      8 エリーチカ!
      9 要写出来Хорошо的代码哦~
     10 */
     11 
     12 #include <cstdio>
     13 #include <algorithm>
     14 #include <cstring>
     15 #include <cmath>
     16 #include <string>
     17 #include <iostream>
     18 #include <vector>
     19 #include <list>
     20 #include <queue>
     21 #include <stack>
     22 #include <map>
     23 using namespace std;
     24 
     25 //DEBUG MODE
     26 #define debug 0
     27 
     28 //循环
     29 #define REP(n) for(int o=0;o<n;o++)
     30 
     31 int C,G;//C钩子数 G砝码数
     32 const int maxn = 25;
     33 int hook[maxn];//hook钩子位置
     34 int weight[maxn];//weight砝码重量
     35 
     36 int dp[maxn][15005];
     37 
     38 bool Do() {
     39     if(scanf("%d%d",&C,&G) == EOF)
     40         return false;
     41     REP(C)
     42         scanf("%d",&hook[o+1]);
     43     REP(G)
     44         scanf("%d",&weight[o+1]);
     45 
     46     //DP
     47     /*
     48         状态分析
     49 
     50         采用动态规划,可以看出有一维是使用前i个砝码
     51         最后一层的意义是:将第i个砝码加入到天平系统中,使天平达到平衡
     52         则每一层的意义是:将第i个砝码加入到天平系统中,使天平达到特定的状态
     53         对于天平来说,平衡状态可以用力矩表示
     54 
     55         i为使用的砝码个数 j为力矩
     56         答案应该为dp[G][0],即使用G个砝码(全部用完),并且力矩为0(保持平衡)
     57         初始状态为dp[0][0]=1(使用前0个砝码时保持平衡,即不放置砝码平衡)
     58 
     59         按照样例有:
     60         dp[4][0]=dp[3][16]+dp[3][-24]
     61             dp[3][16]=dp[2][26]+dp[2][1]
     62                 dp[2][26]=dp[1][34]+dp[1][13]
     63                     dp[1][13]=dp[0][19]+dp[0][4]
     64                     dp[1][34]=dp[0][40]+dp[0][25]
     65                 dp[2][1]=dp[1][9]+dp[1][-11]
     66                     dp[1][9]=dp[0][15]+dp[0][0]
     67                     dp[1][-11]=dp[0][-5]+dp[0][-20]
     68             dp[3][-24]=dp[2][-14]+dp[2][-39]
     69                 dp[2][-14]=dp[1][-6]+dp[1][-28]
     70                     dp[1][-6]=dp[0][0]+dp[0][-15]
     71                     dp[1][-28]=dp[0][-22]+dp[0][-37]
     72                 dp[2][-39]=dp[1][-31]+dp[1][-51]
     73                     dp[1][-31]=dp[0][-25]+dp[0][-40]
     74                     dp[1][-51]=dp[0][-45]+dp[0][-60]
     75 
     76         dp[i][j]=dp[i-1][j-weight[i]*hook[0]]+dp[i-1][j-weight[i]*hook[1]]+......
     77         即 使用i个砝码且力矩为j 等于 使用i-1个砝码且力矩为(j减去砝码i可能的力矩)
     78 
     79         也即dp[i][j]+=dp[i-1][j-weight[i]*hook[k]] k=0,1......k-1
     80 
     81         由于下标不能为负数,因此要将力矩变为正数
     82         钩子在-15~+15之间 砝码最多20个,每个最终25 即力矩最大为 15*20*25=7500
     83 
     84         原力矩范围为 -7500~0~7500
     85         加上7500后有 0~7500~15000
     86 
     87     */
     88     memset(dp,0,sizeof(dp));
     89 
     90     dp[0][0+7500] = 1;
     91     for(int i = 1;i <= G;i++)
     92         for(int j = 1;j <= 15000;j++)
     93             for(int k = 1;k <= C;k++)
     94                 if(j - weight[i] * hook[k] >= 0 && j-weight[i]*hook[k]<=15000)
     95                     dp[i][j] += dp[i - 1][j - weight[i] * hook[k]];
     96 
     97     printf("%d
    ",dp[G][7500]);
     98 
     99     return true;
    100 }
    101 
    102 int main() {
    103     while(Do());
    104     return 0;
    105 }
  • 相关阅读:
    java-并发解决方案
    linux-常用快捷键
    java-进程
    vim-常用快捷键
    数据库-事务
    spring-事务实现原理
    gdb
    x86 下的 struct 變數 member 擺放位置
    du 查看 資料夾 佔用空間
    ADC 計算時,階數的選擇
  • 原文地址:https://www.cnblogs.com/ohyee/p/5433389.html
Copyright © 2020-2023  润新知