题意:给你一个天枰,再给你秤上一些挂钩的位置和秤砣,让你计算用这些钩子和秤砣使这个天枰平衡的方法数(秤砣必须全部使用)
题外话:这道是学长去年的Dp练习题,今天拿来做一下,刚开始的时候感觉这个题根本和Dp根本不占边呀(还是太弱了),之后去请教了一下隔壁寝室的大神,感觉豁然开朗。
思路:dp[i][j]表示用前i种秤砣,组成质量为j时的方法数,因为左边的挂钩是带重量的,而每个秤砣在天枰上产生的实际重量应该是 挂钩的位置*秤砣的质量 ,所以j就可能为负值,C++不支持带负数的数组,所以就把所有的权重+10000(大致计算了一下 这些秤砣产生的最大重量不可能超过一万),随意此时天秤的平衡状态就是j=10000的状态,最后输出dp[G][10000]。将dp数组初始化为零,将dp[0][10000]设成1(天枰本来就是平衡的)。
Code:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define SIZE_M 25
#define SIZE_N 20005
#define INF 100000000
int dp[SIZE_M][SIZE_N];
int c[SIZE_M];
int g[SIZE_M];
int C,G;
int main()
{
scanf("%d%d",&C,&G);
for(int i=0;i<C;i++) scanf("%d",&c[i]);
for(int i=1;i<=G;i++) scanf("%d",&g[i]);
memset(dp,0,sizeof(dp));
dp[0][10000]=1;
for(int i=1;i<=G;i++){
for(int j=0;j<20000;j++){
if(dp[i-1][j]){
for(int k=0;k<C;k++) dp[i][j+g[i]*c[k]]+=dp[i-1][j];
}
}
}
printf("%d\n",dp[G][10000]);
return 0;
}
总结: 这道题其实是背包问题很相似,在这两个问题中i都表示使用前i种物品,j都表示使用前i种物品所产生的一种属性,dp数组都是用来存最终结果,更新过程都是根据i-1的
所有j的值来更新所有i的j值,这其实是一种思维的方式,深悟,理解,体会~