題目大意:
有一個天平,天平左右兩邊各有若干個鉤子,總共有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];
}