此题第一印象想到的是穷举,但是肯定会超时。根据题意假设有一平衡因子j,当平衡因子达到0时,天平才会平衡。j>0时天平会向右偏,j<0会向左偏。
由于距离c[i]的范围是-15~15,砝码的重量范围是1~25,砝码的最大数量是20。程序中出现dp[1~20][-15~15]。假设所有的砝码都挂在天平的最左或最右端,平衡因子也就是力矩就会是15*25*20=7500,只要当天平的左端或右端的力矩达到最大力矩的一半3750就不可能再会平衡。dp[C][3750]刚好达到平衡。
dp[i][j]代表当天平上挂i个砝码重量因子达到j时的种类数目。现在就把这个问题分解成小问题,假设已知dp[i-1][j1],则要计算dp[i][j2]时就把dp[i-1][j1]加上,当然dp[i-1][j1]为0时就没必要加了。j1和j2之间相差的就是c*g,c一共有C种,g一共有G种。大致思路就这样了。
#include <stdio.h>
#include <string.h>
#define MAX_num 21
#define MAX 7500
#define balance 3750
int C, G;
int c[MAX_num], g[MAX_num], dp[MAX_num][MAX];
int main()
{
while(scanf("%d%d", &C, &G) != EOF)
{
memset(dp, 0, sizeof(dp));
dp[0][balance] = 1;
for(int i = 0; i < C; i++) scanf("%d", &c[i]);
for(int i = 0; i < G; i++) scanf("%d", &g[i]);
for(int i = 1; i <= G; i++)
{
for(int j = 0; j <= MAX; j++)
{
if(dp[i - 1][j])
{
for(int k = 0; k < C; k++)
{
dp[i][j + c[k] * g[i - 1]] += dp[i - 1][j];
}
}
}
}
printf("%d\n", dp[G][balance]);
}
return 0;
}