题目大意:
有一个天平,天平左右两边各有若干个钩子,总共有C个钩子,有G个钩码,求将钩码全部挂到钩子上使天平平衡的方法的总数。
其中可以把天枰看做一个以x轴0点作为平衡点的横轴
输入:
2 4 //C 钩子数 与 G钩码数
-2 3 //负数:左边的钩子距离天平中央的距离;正数:右边的钩子距离天平中央的距离c[k]
3 4 5 8 //G个重物的质量w[i]
臂力=力距*重量
把每个臂力都当做一个单元。定义一个臂力和j,j的范围是【-25*15*20,25*15*20】力距*重量*极限个数
对每个臂力单元+25*15,那么j的范围就成了[0,15000],而平衡点在7500处;
设dp[j][i]表示放第i个物品时总臂力和为j时能有多少种方法
dp[j-臂力单元][i]+=dp[j][i-1]
所以三重循环为:
for( i =1;i<=g;++i)
for(k=1;k<=c;++k)
for(int j=0;j<=15000;++j)
{
if(j+pos[k]*w[i]>=0&&j+pos[k]*w[i]<=15000)
dp[j+pos[k]*w[i]][i]+=dp[j][i-1]
}
但是当dp[j][i-1]=0时;
for(k=1;k<=c;++k) 的循环是多余的,而把j的循环放在k前,对结果不影响。
所以有
int solve()
{
memset(dp,0,sizeof(dp));
dp[mid][0]=1;
for(int i=1;i<=g;++i)
for(int j=0;j<=MAX_DP;++j)
{
if(dp[j][i-1])//dp[j][i-1]有效时,j+pos[k]*w[i]肯定不会越界
{
for(int k=1;k<=c;++k)
dp[j+pos[k]*w[i]][i]+=dp[j][i-1];
}
}
return dp[mid][g];
}