题意:
就是说一个天平,给了C个距离(坐标),G个砝码,问砝码全用上,有几种让它平衡的办法。
dp[i][j]表示在挂上前i个物体的时,平衡度为j(j>0时表示左边重,j=0时表示天平平衡,j<0时表示右边重)时挂法的数量,而根据题意可以确定j的取值范围为:[-7500,7500],于是可以得到状态转移方程为:
dp[i][j]+=(dp[i-1][j-p[k]*g[i]]), p[k]表示第k个挂钩的位置,g[i]为第i个砝码的重量 由于j-p[k]*g[i]可能为负数,因此统一加上7500,那么初始状态dp[0][7500]=1(此时表示天平平衡),表示不用物体且使得天平平衡时的方法只有一种.
// (1)用二维数组 的 01背包 解。一个一个砝码往上放,头开始 is[0][7500]=1,指0个砝码时为平衡7500,此时有一种方法。
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<string>
int wi[26],dis[26],is[26][15005],C,G;//力矩的极值为-7500,7500.下标为正,故计算时+7500
void ZeroOnepack()
{
int i=0,j,k;
//for(i=1;i<=G;i++)
// {
// for(j=-7500;j<=7500;j++)
// for(k=1;k<=C;k++)
// //if(j+7500>=dis[k]*wi[i])
// is[i][j+7500]+=is[i-1][j+7500-dis[k]*wi[i]];
// }
for(i=1;i<=G;i++)
{
for(j=-7500;j<=7500;j++)
for(k=0; k < C;k++)
//if(j+7500>=dis[k]*wi[i])
is[i][j+7500]+=is[i-1][j+7500-dis[k]*wi[i-1]];//考虑放第i个砝码时的情况数,在第i-1个砝码上加。
}
}
int main()
{
int i=0,tem=0,yz,neg,ws=0,a=1,b=1;
scanf("%d%d",&C,&G);
//for(i=1;i<=C;++i)
//{
// scanf("%d",&dis[i]);
//}
//for(i = 1 ; i <= G ; ++i )
//{
// scanf("%d",&wi[i]);
//}
for(i=0;i<C;++i)
{
scanf("%d",&dis[i]);
}
for(i = 0 ; i < G ; ++i )
{
scanf("%d",&wi[i]);
}
memset(is,0,sizeof(is)/sizeof(int));
is[0][7500]=1;
ZeroOnepack();
printf("%d\n",is[G][7500]);
return 0;
} 2)用一维数组 01背包 解。须用2个一维数组以保证一个物体只能用一次,
因为:假如说只用到f这个数组,不用两个:那么讨论到第i个物体的时候,
f[j]是一个用了i这个物体来达到的状态,但是你f[k]是用f[j]来转移并且用上i的话,
这样f[k]就用了两次i了。二维数组就可以避免这种重复使用,或者用两个一维
数组,每次保证累加时使用的都是没用i时的:当我讨论到i这个物体的时候,先
把之前没讨论到i的状态先存下来,这样每到达一个新状态,都是用没有用到i的
状态tp来转移的,这样的新状态都是用了一次i
//2)用一维数组 01背包 解。须用2个一维数组以保证一个物体只能用一次,
//因为:假如说只用到f这个数组,不用两个:那么讨论到第i个物体的时候,
//f[j]是一个用了i这个物体来达到的状态,但是你f[k]是用f[j]来转移并且用上i的话,
//这样f[k]就用了两次i了。二维数组就可以避免这种重复使用,或者用两个一维
//数组,每次保证累加时使用的都是没用i时的:当我讨论到i这个物体的时候,先
//把之前没讨论到i的状态先存下来,这样每到达一个新状态,都是用没有用到i的
//状态tp来转移的,这样的新状态都是用了一次i
#include<cstdio>
#include<string>
#include<iostream>
#include<cstdlib>
int dp[15002],tp[15002],C,G;
int main()
{
int i,j,k,pos[26],wi[26];
scanf("%d%d",&C,&G);
for(i=0;i<C;++i)
scanf("%d",&pos[i]);
for(i=0;i<G;++i)
scanf("%d",&wi[i]);
dp[7500]=1;
for(i=0;i<G;++i)
{
memcpy(tp,dp,sizeof(dp));
memset(dp,0,sizeof(dp));
for(j=-7500;j<=7500;j++)
for(k=0;k<C;++k)
dp[j+7500]+=tp[j+7500-pos[k]*wi[i]];
}
printf("%d\n",dp[7500]);
return 0;
}