题意:
就是说一个天平,给了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,此时有一种方法。
// (1)用二维数组 的 01背包 解。一个一个砝码往上放,头开始 is[0][7500]=1,指0个砝码时为平衡7500,此时有一种方法。
 #include<cstdio>
#include<cstdio>
 #include<cstdlib>
#include<cstdlib>
 #include<cmath>
#include<cmath>
 #include<string>
#include<string>
 int wi[26],dis[26],is[26][15005],C,G;//力矩的极值为-7500,7500.下标为正,故计算时+7500
int wi[26],dis[26],is[26][15005],C,G;//力矩的极值为-7500,7500.下标为正,故计算时+7500
 void ZeroOnepack()
void ZeroOnepack()


 {
{
 int i=0,j,k;
    int i=0,j,k;
 //for(i=1;i<=G;i++)
    //for(i=1;i<=G;i++)
 //   {
 //   {
 //       for(j=-7500;j<=7500;j++)
 //       for(j=-7500;j<=7500;j++)
 //        for(k=1;k<=C;k++)
 //        for(k=1;k<=C;k++)
 //         //if(j+7500>=dis[k]*wi[i])
 //         //if(j+7500>=dis[k]*wi[i])
 //           is[i][j+7500]+=is[i-1][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(i=1;i<=G;i++)

 
     {
{
 for(j=-7500;j<=7500;j++)
        for(j=-7500;j<=7500;j++)
 for(k=0; k < C;k++)
         for(k=0; k < C;k++)
 //if(j+7500>=dis[k]*wi[i])
          //if(j+7500>=dis[k]*wi[i])
 is[i][j+7500]+=is[i-1][j+7500-dis[k]*wi[i-1]];//考虑放第i个砝码时的情况数,在第i-1个砝码上加。
            is[i][j+7500]+=is[i-1][j+7500-dis[k]*wi[i-1]];//考虑放第i个砝码时的情况数,在第i-1个砝码上加。
 }
    }

 }
}
 int main()
int main()


 {
{

 int i=0,tem=0,yz,neg,ws=0,a=1,b=1;
    int i=0,tem=0,yz,neg,ws=0,a=1,b=1;
 scanf("%d%d",&C,&G);
    scanf("%d%d",&C,&G);
 //for(i=1;i<=C;++i)
    //for(i=1;i<=C;++i)
 //{
    //{
 //    scanf("%d",&dis[i]);
    //    scanf("%d",&dis[i]);
 //}
    //}
 //for(i = 1 ; i <= G ; ++i    )
    //for(i = 1 ; i <= G ; ++i    )
 //{
    //{
 //        scanf("%d",&wi[i]);
    //        scanf("%d",&wi[i]);
 //}
    //}
 for(i=0;i<C;++i)
    for(i=0;i<C;++i)

 
     {
{
 scanf("%d",&dis[i]);
        scanf("%d",&dis[i]);
 }
    }
 for(i = 0 ; i < G ; ++i    )
    for(i = 0 ; i < G ; ++i    )

 
     {
{
 scanf("%d",&wi[i]);
            scanf("%d",&wi[i]);
 }
    }
 memset(is,0,sizeof(is)/sizeof(int));
    memset(is,0,sizeof(is)/sizeof(int));
 is[0][7500]=1;
        is[0][7500]=1;
 ZeroOnepack();
        ZeroOnepack();
 printf("%d\n",is[G][7500]);
        printf("%d\n",is[G][7500]);
 return 0;
        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个一维数组以保证一个物体只能用一次,
//2)用一维数组 01背包 解。须用2个一维数组以保证一个物体只能用一次,
 //因为:假如说只用到f这个数组,不用两个:那么讨论到第i个物体的时候,
//因为:假如说只用到f这个数组,不用两个:那么讨论到第i个物体的时候,
 //f[j]是一个用了i这个物体来达到的状态,但是你f[k]是用f[j]来转移并且用上i的话,
//f[j]是一个用了i这个物体来达到的状态,但是你f[k]是用f[j]来转移并且用上i的话,
 //这样f[k]就用了两次i了。二维数组就可以避免这种重复使用,或者用两个一维
//这样f[k]就用了两次i了。二维数组就可以避免这种重复使用,或者用两个一维
 //数组,每次保证累加时使用的都是没用i时的:当我讨论到i这个物体的时候,先
//数组,每次保证累加时使用的都是没用i时的:当我讨论到i这个物体的时候,先
 //把之前没讨论到i的状态先存下来,这样每到达一个新状态,都是用没有用到i的
//把之前没讨论到i的状态先存下来,这样每到达一个新状态,都是用没有用到i的
 //状态tp来转移的,这样的新状态都是用了一次i
//状态tp来转移的,这样的新状态都是用了一次i
 #include<cstdio>
#include<cstdio>
 #include<string>
#include<string>
 #include<iostream>
#include<iostream>
 #include<cstdlib>
#include<cstdlib>

 int dp[15002],tp[15002],C,G;
int dp[15002],tp[15002],C,G;

 int main()
int main()


 {
{
 int i,j,k,pos[26],wi[26];
    int i,j,k,pos[26],wi[26];
 scanf("%d%d",&C,&G);
    scanf("%d%d",&C,&G);
 for(i=0;i<C;++i)
    for(i=0;i<C;++i)
 scanf("%d",&pos[i]);
        scanf("%d",&pos[i]);
 for(i=0;i<G;++i)
    for(i=0;i<G;++i)
 scanf("%d",&wi[i]);
        scanf("%d",&wi[i]);
 dp[7500]=1;
    dp[7500]=1;
 for(i=0;i<G;++i)
    for(i=0;i<G;++i)

 
         {
{
 memcpy(tp,dp,sizeof(dp));
            memcpy(tp,dp,sizeof(dp));
 memset(dp,0,sizeof(dp));
            memset(dp,0,sizeof(dp));
 for(j=-7500;j<=7500;j++)
            for(j=-7500;j<=7500;j++)
 for(k=0;k<C;++k)
                for(k=0;k<C;++k)
 dp[j+7500]+=tp[j+7500-pos[k]*wi[i]];
                    dp[j+7500]+=tp[j+7500-pos[k]*wi[i]];
 }
    }
 printf("%d\n",dp[7500]);
            printf("%d\n",dp[7500]);
 return 0;
    return 0;

 }
}
