POJ 1837 (DP)

      题目:http://poj.org/problem?id=1837

       一个天平,两个臂,两边有若干挂钩,给若干重物,把重物挂在挂钩上,使天平平衡,所有重物要用完,问一共有多少种方法?

       首先,自定义平衡度(不知有没有):∑重量*力矩

       显然平衡度为0时是平衡的。

       定义balance[i][j]为用完前面 i 个重物,达到平衡度 j 的方法数,为出现负数啊!怎么办?因为最大的挂钩位置15,最大重物重量25,最大的重物数量20,所以最大的平衡度是7500(都在最右边),同理最小的平衡度是-7500,为避免下标为负数,就+7500,于是可定义全局数组 balance[21][15001]。初始平衡态为 balance[0][7500],0表示没放物体,7500是平衡的,因为逆着转回去就是0了撒!

 

       既然是动态规划,就要找到子问题,定义状态,找到状态转移方程。

      状态:balance[i][j]是用完前面 i 个重物,达到平衡度 j 的方法数

      子问题:要知道balance[i][j] 只需知道没放第 i 个重物时的过渡状态(就是通过把第i个重物放在某个挂钩可以达到平衡度j),或者转化下:balance[i-1][j]把第i个重物放到某个位置达到的新的状态(便于代码实现)

      状态转移方程: balance[i][ j+hook[k]*weight[i] ] += balance[i-1][j]; (i表示重物的下标,k表示挂钩的下标,j表示平衡度)

 

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int balance[21][15001],hook[21],weight[21];

int main()
{
   int h,w,i,j,k;
   
     while(scanf("%d%d",&h,&w) != EOF )
     {
        for(i = 1 ; i <= h ; ++i)
        scanf("%d",hook+i);
        
        for(i = 1 ; i <= w ; ++i)
        scanf("%d",weight+i);                          
       
        /*
          初始化 
        */
        memset(balance,0,sizeof(balance));
        balance[0][7500] = 1;
        
        /*
          动态规划 
        */ 
         for(i = 1 ; i <= w ; ++i)//遍历重物 
         {
             for(j = 15000 ; j >= 0 ; --j)//平衡度 
             {
                   if(balance[i-1][j])
                     for(k = 1 ; k <= h;++k)//求下一状态 
                     balance[i][ j+hook[k]*weight[i] ] += balance[i-1][j];       
             }
         }
         
           printf("%d\n",balance[w][7500]);
     }
     
   //system("pause");
   return 0;    
}

  

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/HpuAcmer/archive/2012/04/13/2446431.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值