POJ 1837 Balance 0-1背包

背包DP

题意:有一杆秤,秤上有c个挂钩(2<=c<=20)(在左为负,在右为正,范围-15—15),另有g(2<=g<=20)个砝码(质量各不相同,范围1-25),要 求把所有砝码挂到挂钩上能使秤平衡的种数。

分析:每个砝码必须放在c个挂钩上的其中一个。

用数组dp[i][j](j表示一个状态,力矩+7500)表示放完第i个砝码后,各个状态存在的种数;

确定数组范围:显然0<=i<=20,而对于j,取最极端的数据, 挂钩在15位置,g=20,质量都为25,则计算得力矩最大值15*25*20=7500;挂钩在-15时,同理得力矩最大值-7500;为了避免出现负数,j为力矩+7500;

初始化:平衡点,没有砝码,dp[0][7500]=1;

状态转移方程:

if(dp[i-1][j])dp[i][j+a[k]*b[i]]+=dp[i-1][j];   (1<=k<=c)

AC代码:

View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[23][15003];
int a[23],b[23];
int main()
{
    int c, g, i, j ,k;
    while(~scanf("%d%d",&c,&g))
    {
        memset(dp,0,sizeof(dp));
        for(i=1;i<=c;i++)
            scanf("%d",&a[i]);
        for(i=1;i<=g;i++)
            scanf("%d",&b[i]);
        dp[0][7500]=1;
        for(i=1;i<=g;i++)
        {
            for(j=0;j<=15000;j++)
                if(dp[i-1][j])
                    for(k=1;k<=c;k++)
                        dp[i][j+a[k]*b[i]]+=dp[i-1][j];
        }
        printf("%d\n",dp[g][7500]);
    }
    return 0;
}

 

posted @ 2012-08-07 09:43  To be an ACMan  Views(209)  Comments(0)    收藏  举报