poj-1837 Balance【dp】

题目大意:

有一个天平,天平左右两边各有若干个钩子,总共有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];
}


你可能感兴趣的:(poj-1837 Balance【dp】)